#IMPORTANT NOTE: everything for plotting in figures currently comes from the second_timepoint object, but there are additional chunks that run similar analyses on all_data objects with different cluster numbers

#Set working directory to appropriate folder for inputs and outputs on Google Drive

#Initialize

Load data

rm(list = ls())
library(dplyr)
library(Seurat)
library(ggplot2)
library(RColorBrewer)
library(xlsx)

cluster second timepoint and plot

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Preprocess_GEX/Objects_premerged.RData')
load('2022_01_14_analysis_scripts/2022_05_27_analysis/Preprocess_GEX/second_timepoint_merged.RData')
load('2022_01_14_analysis_scripts/2022_05_27_analysis/Preprocess_GEX/first_timepoint_merged.RData')

This is the same chunk as above but it makes the plots as bar charts in individual PDFs for pulling into illustrator

second_timepoint <- NormalizeData(second_timepoint)
Performing log-normalization
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
second_timepoint <- FindVariableFeatures(second_timepoint, selection.method = 'vst', nFeatures = 20000)
Warning: The following arguments are not used: nFeatures
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
second_timepoint <- ScaleData(second_timepoint)
Centering and scaling data matrix

  |                                                                                                                                     
  |                                                                                                                               |   0%
  |                                                                                                                                     
  |================================================================                                                               |  50%
  |                                                                                                                                     
  |===============================================================================================================================| 100%
second_timepoint <- RunPCA(second_timepoint)
PC_ 1 
Positive:  IGFBP7, COL1A1, BASP1, TPM1, CAV1, ARL4C, FN1, RTN4, MMP2, TXNRD1 
       C12orf75, CALD1, SPOCK1, THBS1, MYL6, ANXA1, COL6A1, TPM4, CALM2, IL6ST 
       COL6A2, MYOF, PRNP, C1R, TMSB4X, DSTN, CRIM1, ANXA2, SFRP1, CEMIP 
Negative:  PMEL, MLANA, LHFPL3-AS1, FRMD4B, DCT, S100B, CAPN3, PRDX1, BCAS3, APOD 
       RAMP1, VGF, RGS1, IRS2, C11orf96, RLBP1, CITED1, BAAT, AKR1A1, LINC01531 
       FABP7, SCML4, CEACAM1, ATP6V0D2, CSTB, EDNRB, HSPA1A, CPM, TRIM63, TRPM1 
PC_ 2 
Positive:  MT2A, TMEM158, MMP1, STC1, CCND1, SCG2, IER3, PHLDA1, TFPI2, KYNU 
       VEGFA, SFRP1, LINC02376, WNT5A, SERPINB2, HPCAL1, AKR1B1, SIRPB1, GNG11, EREG 
       LTBP1, ITGA2, MYEOV, CD44, SLC16A6, MMP3, ANGPTL4, NRP1, TIMP3, MAP4K4 
Negative:  CRYAB, IFI6, S100B, AEBP1, SPARC, MFGE8, PMP22, SORBS2, C1orf198, LIMA1 
       PALLD, ANK3, CTSK, COL9A3, HSPG2, IFITM3, LIMCH1, GREM2, PLP1, SCRG1 
       GAS7, CEBPD, OLFML2A, ISG15, EPB41L3, AKAP12, IFI27, APOE, LMCD1, NUPR1 
PC_ 3 
Positive:  MALAT1, FTH1, FTL, NEAT1, MMP1, FN1, NDRG1, SCG2, IGFBP5, RND3 
       TIMP1, CEBPD, GAS5, ADM, DEPP1, RGS2, IGFBP7, LINC00968, INHBA, JUN 
       STC1, ARL4C, UBC, IL6ST, TMSB4X, TFPI2, NNMT, PTGS2, FGF7, IER3 
Negative:  MKI67, CENPF, TPX2, ASPM, UBE2S, NUSAP1, GTSE1, ANLN, TOP2A, H2AFZ 
       BIRC5, PRC1, HIST1H1B, UBE2C, HIST1H4C, TMPO, TUBA1B, CEP55, CENPE, HMGB2 
       CCNB1, HMMR, TK1, NCAPG, PRR11, PCLAF, AURKB, UBE2T, DBF4, CDKN3 
PC_ 4 
Positive:  OLFML2A, EPB41L3, HSPG2, COL9A3, NGFR, CRYAB, ITGA6, ITGA2, SCRG1, DLX5 
       SEMA3B, H19, TSPAN13, GAS7, NCAM1, TRIM58, NTRK2, SERPINE2, ANK3, NFATC2 
       TSC22D1, SLITRK6, MAP4K4, EVI5, PHACTR1, LRRTM4, AKAP12, GRIK2, HTRA1, MALAT1 
Negative:  BST2, IFI27, VCAM1, COL14A1, XAF1, APOE, SFRP4, LINC00968, C1R, LINC01914 
       GBP1, DEPP1, CTSK, CARD16, IFI44L, PDE5A, PLAAT4, GYPC, DCN, PSMB9 
       NUPR1, LBP, FOSB, TSLP, NNMT, CCL2, BGN, C1S, RPS27L, IFITM3 
PC_ 5 
Positive:  VCAM1, IGFBP5, BOC, COL14A1, FOXF1, KYNU, PLAAT4, CTSC, MMD, CARD16 
       TRPA1, C1R, LBP, PDGFRA, IRF1, PMEPA1, PCDH18, WNT5A, FENDRR, CASP1 
       DCN, CSRP2, LAMB1, SOST, AGT, TBX2, MGST1, SLC7A11, FOXF2, FAM20C 
Negative:  CPA4, KRT34, SERPINE1, SMYD3, LINC01638, AC092807.3, DKK1, C12orf75, TNIK, FGF5 
       OXTR, SRGN, SPOCK1, CDA, CCN5, GRAMD2B, ARL4C, EPGN, SPOCD1, SCG5 
       MME, CRISPLD2, TPST2, STON2, TNFRSF12A, CSTB, RPS27L, GCNT1, LMO7, RASD2 
second_timepoint <- FindNeighbors(second_timepoint, dims = 1:15)
Computing nearest neighbor graph
Computing SNN
second_timepoint <- FindClusters(second_timepoint, resolution = 0.5)
Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 57996
Number of edges: 1751932

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.9022
Number of communities: 14
Elapsed time: 13 seconds
second_timepoint <- RunUMAP(second_timepoint, dims = 1:15)
09:22:25 UMAP embedding parameters a = 0.9922 b = 1.112
09:22:25 Read 57996 rows and found 15 numeric columns
09:22:25 Using Annoy for neighbor search, n_neighbors = 30
09:22:25 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
09:22:30 Writing NN index file to temp file /var/folders/ph/24prrxys02179y9_qzhxjgvc0000gn/T//RtmpH55A7T/file13f1572bdbb96
09:22:31 Searching Annoy index using 1 thread, search_k = 3000
09:22:48 Annoy recall = 100%
09:22:48 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
09:22:50 Initializing from normalized Laplacian + noise (using irlba)
09:22:52 Commencing optimization for 200 epochs, with 2501536 positive edges
Using method 'umap'
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
09:23:25 Optimization finished
cells_per_cluster <- data.frame (Cluster = as.numeric(second_timepoint$seurat_clusters), Condition = second_timepoint$OG_condition)
cells_per_cluster_list <- list()

pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/original_condition_second_timepoint.pdf')
print(DimPlot(second_timepoint))
print(DimPlot(second_timepoint, label = T, group.by = 'OG_condition', cols = c('dabtramtodabtram' = '#561E59', 'dabtramtococl2' = '#A2248E', 'dabtramtocis' = '#9D85BE', 'cocl2todabtram' = '#10413B', 'cocl2tococl2' = '#6ABD45', 'cocl2tocis' = '#6DC49C', 'cistodabtram' = '#A23622', 'cistococl2' = '#F49129', 'cistocis' = '#FBD08C')))

for (i in 1:(max(cells_per_cluster$Cluster))){
  currentcluster <- filter(cells_per_cluster, cells_per_cluster$Cluster == i)
  cells_per_cluster_list[[paste0('Cluster', i)]] <- data.frame(table(currentcluster$Condition))
  
  print(ggplot(cells_per_cluster_list[[paste0('Cluster', i)]], aes(x ='', y = Freq, fill = Var1)) + geom_bar(stat = 'identity') + coord_polar('y', start = 0) + theme_void() + scale_fill_manual(values = c('dabtramtodabtram' = '#561E59', 'dabtramtococl2' = '#A2248E', 'dabtramtocis' = '#9D85BE', 'cocl2todabtram' = '#10413B', 'cocl2tococl2' = '#6ABD45', 'cocl2tocis' = '#6DC49C', 'cistodabtram' = '#A23622', 'cistococl2' = '#F49129', 'cistocis' = '#FBD08C')) + labs(title = paste('Original condition of cells in cluster', i-1)))
}
Warning: stack imbalance in 'lapply', 83 then 81
dev.off()
null device 
          1 

#editing cells_per_cluster so that the condition name is whatever second condition

#UMAPs highlighting all cells that had same first and second drug in second_timepoint object


cells_per_cluster_seconddrug <- cells_per_cluster
cells_per_cluster_firstdrug <- cells_per_cluster

for (i in 1:nrow(cells_per_cluster)){
  if (cells_per_cluster$Condition[[i]] == "dabtramtodabtram" || cells_per_cluster$Condition[[i]] == "cistodabtram" || cells_per_cluster$Condition[[i]] == "cocl2todabtram") {
    cells_per_cluster_seconddrug$Condition[[i]] <- "dabtramsecond"
  }
  if (cells_per_cluster$Condition[[i]] == "cocl2tococl2" || cells_per_cluster$Condition[[i]] == "cistococl2" || cells_per_cluster$Condition[[i]] == "dabtramtococl2") {
    cells_per_cluster_seconddrug$Condition[[i]] <- "cocl2second"
  }
  if (cells_per_cluster$Condition[[i]] == "cistocis" || cells_per_cluster$Condition[[i]] == "cocl2tocis" || cells_per_cluster$Condition[[i]] == "dabtramtocis") {
    cells_per_cluster_seconddrug$Condition[[i]] <- "cissecond"
  }
}

for (i in 1:nrow(cells_per_cluster)){
  if (cells_per_cluster$Condition[[i]] == "dabtramtodabtram" || cells_per_cluster$Condition[[i]] == "dabtramtocis" || cells_per_cluster$Condition[[i]] == "dabtramtococl2") {
    cells_per_cluster_firstdrug$Condition[[i]] <- "dabtramfirst"
  }
  if (cells_per_cluster$Condition[[i]] == "cocl2tococl2" || cells_per_cluster$Condition[[i]] == "cocl2tocis" || cells_per_cluster$Condition[[i]] == "cocl2todabtram") {
    cells_per_cluster_firstdrug$Condition[[i]] <- "cocl2first"
  }
  if (cells_per_cluster$Condition[[i]] == "cistocis" || cells_per_cluster$Condition[[i]] == "cistococl2" || cells_per_cluster$Condition[[i]] == "cistodabtram") {
    cells_per_cluster_firstdrug$Condition[[i]] <- "cisfirst"
  }
}

#now colored based on second drug only
for (i in 1:(max(cells_per_cluster_seconddrug$Cluster))){
  pdf(paste0('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/end_condition_second_timepoint', i-1, '.pdf'))
  currentcluster <- filter(cells_per_cluster_seconddrug, cells_per_cluster_seconddrug$Cluster == i)
  cells_per_cluster_list[[paste0('Cluster', i)]] <- data.frame(table(currentcluster$Condition))
  
  print(ggplot(cells_per_cluster_list[[paste0('Cluster', i)]], aes(x ='', y = Freq, fill = Var1)) + geom_bar(position = 'fill', stat = 'identity') + scale_fill_manual(values = c('dabtramsecond' = '#623594', 'cocl2second' = '#0F8241', 'cissecond' = '#C96D29')) + labs(title = paste('End condition of cells in second timepoint cluster', i-1)))
  dev.off()
}

#now colored based on first drug only
for (i in 1:(max(cells_per_cluster_firstdrug$Cluster))){
  pdf(paste0('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/first_condition_second_timepoint', i-1, '.pdf'))
  currentcluster <- filter(cells_per_cluster_firstdrug, cells_per_cluster_firstdrug$Cluster == i)
  cells_per_cluster_list[[paste0('Cluster', i)]] <- data.frame(table(currentcluster$Condition))
  
  print(ggplot(cells_per_cluster_list[[paste0('Cluster', i)]], aes(x ='', y = Freq, fill = Var1)) + geom_bar(position = 'fill', stat = 'identity') + scale_fill_manual(values = c('dabtramfirst' = '#623594', 'cocl2first' = '#0F8241', 'cisfirst' = '#C96D29')) + labs(title = paste('End condition of cells in first timepoint cluster', i-1)))
  dev.off()
}

#UMAPs highlighting all cells that had same first drug in first_timepoint object

cells_per_condition <- list()
for (i in c('dabtramtodabtram', 'dabtramtococl2', 'dabtramtocis', 'cocl2todabtram', 'cocl2tococl2', 'cocl2tocis', 'cistodabtram', 'cistococl2', 'cistocis')){
  cells_per_condition[[paste0(i, '_cells')]] <- names(second_timepoint$orig.ident[second_timepoint$OG_condition == i])
}

pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/drug_group_highlights.pdf')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$dabtramtodabtram_cells, cells_per_condition$dabtramtocis_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = ('red')) + ggtitle('dabtram first cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = ('red')) + ggtitle('cocl2 first cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cistococl2_cells, cells_per_condition$cistodabtram_cells),
        cols.highlight = ('red')) + ggtitle('cis first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$dabtramtodabtram_cells, cells_per_condition$cistodabtram_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = ('blue')) + ggtitle('dabtram second cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cistococl2_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = ('blue')) + ggtitle('cocl2 second cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$dabtramtocis_cells),
        cols.highlight = ('blue')) + ggtitle('cis second cells')

dev.off()
null device 
          1 

#More plots not in PDF but just for quick visualizations

pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/drug_group_highlights_first_timepoint.pdf')

DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = "OG_condition", pt.size = 2, cols =  c('dabtram' = '#623594', 'cocl2' = '#0F8241', 'cis' = '#C96D29'))
DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(names(first_timepoint$orig.ident[first_timepoint$OG_condition == 'dabtram'])),
        cols.highlight = ('red')) + ggtitle('dabtram first cells')
DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(names(first_timepoint$orig.ident[first_timepoint$OG_condition == 'cocl2'])),
        cols.highlight = ('red')) + ggtitle('cocl2 first cells')
DimPlot(first_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(names(first_timepoint$orig.ident[first_timepoint$OG_condition == 'cis'])),
        cols.highlight = ('red')) + ggtitle('cis first cells')

FeaturePlot(first_timepoint, features = 'EGFR', pt.size = 2) +
  scale_colour_gradientn(colors = rev(brewer.pal(n = 11, name = 'RdBu')))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
FeaturePlot(first_timepoint, features = 'NGFR', pt.size = 2) +
  scale_colour_gradientn(colors = rev(brewer.pal(n = 11, name = 'RdBu')))
Scale for 'colour' is already present. Adding another scale for 'colour', which will replace the existing scale.
dev.off()
null device 
          1 
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = c('#10413b', '#6dc49c', '#6abd45')) + ggtitle('cocl2 first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$cocl2todabtram_cells),
        cols.highlight = ('#0f8241')) + ggtitle('cocl2 first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cistococl2_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = c('#a2248e', '#f49129', '#6abd45')) + ggtitle('cocl2 second cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cocl2tococl2_cells, cells_per_condition$cistococl2_cells, cells_per_condition$dabtramtococl2_cells),
        cols.highlight = ('#0f8241')) + ggtitle('cocl2 second cells')
DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cistococl2_cells, cells_per_condition$cistodabtram_cells),
        cols.highlight = c('#a23622', '#f49129', '#fbd08c')) + ggtitle('cis first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cistococl2_cells, cells_per_condition$cistodabtram_cells),
        cols.highlight = ('#c96d29')) + ggtitle('cis first cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$dabtramtocis_cells),
        cols.highlight = c('#9d85be', '#6dc49c', '#fbd08c')) + ggtitle('cis second cells')

DimPlot(second_timepoint, reduction = "umap", dims = c(1,2), group.by = 'OG_condition', pt.size = .1,
        cells.highlight = list(cells_per_condition$cis_cells, cells_per_condition$cistocis_cells, cells_per_condition$cocl2tocis_cells, cells_per_condition$dabtramtocis_cells),
        cols.highlight = ('#c96d29')) + ggtitle('cis second cells')

Save the object to load in for distance metrics

save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace.RData')

Run distance metrics

save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace.RData')

Try pearson - https://pubmed.ncbi.nlm.nih.gov/30137247/

# Define manhatten distance function
manhattan.distance <- function(x, y) return(sum(abs(x-y)))

# Make metadata objects of the first and second conditions
second_timepoint$first_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 1)
second_timepoint$second_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 2)

# Get input data and subest
input_data <- GetAssayData(second_timepoint, assay = 'RNA', slot = 'scale.data')

# Number of cells for subsetting
num_cells <- 10000

# Look at grouping based on first sample
Idents(second_timepoint) <- second_timepoint$first_treatment
DimPlot(second_timepoint)


cocl2_first_cells <-  sample(names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cocl2'], num_cells)
cocl2_first_subset <- input_data[,cocl2_first_cells]
cocl2_first_manhatten_distance <- CustomDistance(cocl2_first_subset, manhattan.distance)

dabtram_first_cells <-  sample(names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'dabtram'], num_cells)
dabtram_first_subset <- input_data[,dabtram_first_cells]
dabtram_first_manhatten_distance <- CustomDistance(dabtram_first_subset, manhattan.distance)

cis_first_cells <-  sample(names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cis'], num_cells)
cis_first_subset <- input_data[,cis_first_cells]
cis_first_manhatten_distance <- CustomDistance(cis_first_subset, manhattan.distance)

Idents(second_timepoint) <- second_timepoint$second_treatment
DimPlot(second_timepoint)


cocl2_second_cells <-  sample(names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cocl2'], num_cells)
cocl2_second_subset <- input_data[,cocl2_second_cells]
cocl2_second_manhatten_distance <- CustomDistance(cocl2_second_subset, manhattan.distance)

dabtram_second_cells <-  sample(names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'dabtram'], num_cells)
dabtram_second_subset <- input_data[,dabtram_second_cells]
dabtram_second_manhatten_distance <- CustomDistance(dabtram_second_subset, manhattan.distance)

cis_second_cells <-  sample(names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cis'], num_cells)
cis_second_subset <- input_data[,cis_second_cells]
cis_second_manhatten_distance <- CustomDistance(cis_second_subset, manhattan.distance)

plotting_df <- data.frame(Grouping = c(rep('first',3*length(cis_first_manhatten_distance)),rep('second', 3*(length(cis_second_manhatten_distance)))),
                          Manhatten_dist <- c(cocl2_first_manhatten_distance, dabtram_first_manhatten_distance, cis_first_manhatten_distance, cocl2_second_manhatten_distance,dabtram_second_manhatten_distance, cis_second_manhatten_distance),
                          Treatment = c(rep('CoCl2 first',length(cocl2_first_manhatten_distance)),rep('Dab/Tram first',length(dabtram_first_manhatten_distance)),rep('Cisplatin first',length(cis_first_manhatten_distance)),rep('CoCl2 second',length(cocl2_second_manhatten_distance)),rep('Dab/Tram second',length(dabtram_second_manhatten_distance)),rep('Cisplatin second',length(cis_second_manhatten_distance))))

ggplot(plotting_df, aes(x = Treatment, y = Manhatten_dist, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1)


save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace_v2.RData')

Statistical analysis and plotting of pearson metrics - CoCl2


#load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace_v2.RData')

rm(manhatten.distance, cocl2_first_manhatten_distance, dabtram_first_manhatten_distance, cis_first_manhatten_distance, cocl2_second_manhatten_distance, dabtram_second_manhatten_distance, cis_second_manhatten_distance)
Warning in rm(manhatten.distance, cocl2_first_manhatten_distance, dabtram_first_manhatten_distance,  :
  object 'manhatten.distance' not found
rm(cis, cistocis, cistococl2, cistodabtram, cocl2, cocl2tocis, cocl2tococl2, cocl2todabtram, dabtram, dabtramtocis, dabtramtococl2, dabtramtodabtram)
gc()
             used    (Mb) gc trigger    (Mb) limit (Mb)   max used    (Mb)
Ncells    4100917   219.1    6815804   364.1         NA    6815804   364.1
Vcells 1630180427 12437.3 7909077067 60341.5     102400 9886346333 75426.9
# Make metadata objects of the first and second conditions
second_timepoint$first_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 1)
second_timepoint$second_treatment <- sapply(strsplit(second_timepoint$OG_condition, "to"), "[[", 2)

# Get input data and subest
input_data <- GetAssayData(second_timepoint, assay = 'RNA', slot = 'scale.data')


# Look at grouping based on first sample
Idents(second_timepoint) <- second_timepoint$first_treatment
DimPlot(second_timepoint)


cocl2_first_cells <-  names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cocl2']
cocl2_first_subset <- input_data[,cocl2_first_cells]
cocl2_first_pearson <- cor(cocl2_first_subset)
cocl2_first_pearson_filt <- cocl2_first_pearson[lower.tri(cocl2_first_pearson, diag = FALSE)]

set.seed(1)
cocl2_first_subset_rand <- input_data[,sample(colnames(input_data),length(cocl2_first_cells))]
cocl2_first_pearson_rand <- cor(cocl2_first_subset_rand)
cocl2_first_pearson_filt_rand <- cocl2_first_pearson_rand[lower.tri(cocl2_first_pearson_rand, diag = FALSE)]

dabtram_first_cells <-  names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'dabtram']
dabtram_first_subset <- input_data[,dabtram_first_cells]
dabtram_first_pearson <- cor(dabtram_first_subset)
dabtram_first_pearson_filt <- dabtram_first_pearson[lower.tri(dabtram_first_pearson, diag = FALSE)]

set.seed(1)
dabtram_first_subset_rand <- input_data[,sample(colnames(input_data),length(dabtram_first_cells))]
dabtram_first_pearson_rand <- cor(dabtram_first_subset_rand)
dabtram_first_pearson_filt_rand <- dabtram_first_pearson_rand[lower.tri(dabtram_first_pearson_rand, diag = FALSE)]

cis_first_cells <-  names(second_timepoint$first_treatment)[second_timepoint$first_treatment == 'cis']
cis_first_subset <- input_data[,cis_first_cells]
cis_first_pearson <- cor(cis_first_subset)
cis_first_pearson_filt <- cis_first_pearson[lower.tri(cis_first_pearson, diag = FALSE)]

set.seed(1)
cis_first_subset_rand <- input_data[,sample(colnames(input_data),length(cis_first_cells))]
cis_first_pearson_rand <- cor(cis_first_subset_rand)
cis_first_pearson_filt_rand <- cis_first_pearson_rand[lower.tri(cis_first_pearson_rand, diag = FALSE)]

Idents(second_timepoint) <- second_timepoint$second_treatment
DimPlot(second_timepoint)


cocl2_second_cells <-  names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cocl2']
cocl2_second_subset <- input_data[,cocl2_second_cells]
cocl2_second_pearson <- cor(cocl2_second_subset)
cocl2_second_pearson_filt <- cocl2_second_pearson[lower.tri(cocl2_second_pearson, diag = FALSE)]

set.seed(1)
cocl2_second_subset_rand <- input_data[,sample(colnames(input_data),length(cocl2_second_cells))]
cocl2_second_pearson_rand <- cor(cocl2_second_subset_rand)
cocl2_second_pearson_filt_rand <- cocl2_second_pearson_rand[lower.tri(cocl2_second_pearson_rand, diag = FALSE)]

dabtram_second_cells <-  names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'dabtram']
dabtram_second_subset <- input_data[,dabtram_second_cells]
dabtram_second_pearson <- cor(dabtram_second_subset)
dabtram_second_pearson_filt <- dabtram_second_pearson[lower.tri(dabtram_second_pearson, diag = FALSE)]

set.seed(1)
dabtram_second_subset_rand <- input_data[,sample(colnames(input_data),length(dabtram_second_cells))]
dabtram_second_pearson_rand <- cor(dabtram_second_subset_rand)
dabtram_second_pearson_filt_rand <- dabtram_second_pearson_rand[lower.tri(dabtram_second_pearson_rand, diag = FALSE)]

cis_second_cells <-  names(second_timepoint$second_treatment)[second_timepoint$second_treatment == 'cis']
cis_second_subset <- input_data[,cis_second_cells]
cis_second_pearson <- cor(cis_second_subset)
cis_second_pearson_filt <- cis_second_pearson[lower.tri(cis_second_pearson, diag = FALSE)]

set.seed(1)
cis_second_subset_rand <- input_data[,sample(colnames(input_data),length(cis_second_cells))]
cis_second_pearson_rand <- cor(cis_second_subset_rand)
cis_second_pearson_filt_rand <- cis_second_pearson_rand[lower.tri(cis_second_pearson_rand, diag = FALSE)]

save.image('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/workspace_v3.RData')

# Save CoCl2 outputs
save(cocl2_first_pearson, cocl2_first_pearson_rand, cocl2_first_subset, cocl2_first_subset_rand, cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson, cocl2_second_pearson_rand, cocl2_second_subset, cocl2_second_subset_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_results.RData')
rm(cocl2_first_pearson, cocl2_first_pearson_rand, cocl2_first_subset, cocl2_first_subset_rand, cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson, cocl2_second_pearson_rand, cocl2_second_subset, cocl2_second_subset_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand)

# Save dabtram outputs
save(dabtram_first_pearson, dabtram_first_pearson_rand, dabtram_first_subset, dabtram_first_subset_rand, dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson, dabtram_second_pearson_rand, dabtram_second_subset, dabtram_second_subset_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_results.RData')
rm(dabtram_first_pearson, dabtram_first_pearson_rand, dabtram_first_subset, dabtram_first_subset_rand, dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson, dabtram_second_pearson_rand, dabtram_second_subset, dabtram_second_subset_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand)

# Save cis outputs
save(cis_first_pearson, cis_first_pearson_rand, cis_first_subset, cis_first_subset_rand, cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson, cis_second_pearson_rand, cis_second_subset, cis_second_subset_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_results.RData')
rm(cis_first_pearson, cis_first_pearson_rand, cis_first_subset, cis_first_subset_rand, cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson, cis_second_pearson_rand, cis_second_subset, cis_second_subset_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand)

Statistical analysis and plotting of pearson metrics - dabtram

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_results.RData') # Load data

pearson_ttest_cocl2_firstvsrand <- t.test(cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand,  paired = F)
pearson_ttest_cocl2_secondvsrand <- t.test(cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand,  paired = F)
pearson_ttest_cocl2_secondvsfirst <- t.test(cocl2_second_pearson_filt, cocl2_first_pearson_filt,  paired = F)
pearson_ttest_cocl2_randvsrand <- t.test(cocl2_second_pearson_filt_rand, cocl2_first_pearson_filt_rand,  paired = F)

rm(cocl2_first_pearson, cocl2_first_pearson_rand, cocl2_first_subset, cocl2_first_subset_rand, cocl2_second_pearson, cocl2_second_pearson_rand, cocl2_second_subset, cocl2_second_subset_rand)

plotting_df_pearson_cocl2 <- data.frame(Grouping = c(rep('first',length(cocl2_first_pearson_filt)), rep('random',length(cocl2_first_pearson_filt)), rep('second', length(cocl2_second_pearson_filt)), rep('random', length(cocl2_second_pearson_filt))),
                          Pearson = c(cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand),
                          Treatment = c(rep('CoCl2 first',length(cocl2_first_pearson_filt)), rep('CoCl2 first rand', length(cocl2_first_pearson_filt_rand)),rep('CoCl2 second',length(cocl2_second_pearson_filt)),rep('CoCl2 second rand',length(cocl2_second_pearson_filt_rand))))
colnames(plotting_df_pearson_cocl2) <- c('Grouping','Pearson','Treatment')

rm(cocl2_first_pearson_filt, cocl2_first_pearson_filt_rand, cocl2_second_pearson_filt, cocl2_second_pearson_filt_rand)
gc()
             used    (Mb)  gc trigger    (Mb) limit (Mb)    max used    (Mb)
Ncells    4102976   219.2     6815804   364.1         NA     6815804   364.1
Vcells 5659627351 43179.6 11389246976 86893.1     102400 11355547725 86636.0
pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_plot_subsampled.pdf')
set.seed(1)
ggplot(plotting_df_pearson_cocl2[sample(1:nrow(plotting_df_pearson_cocl2), 10000000),], aes(x = Treatment, y = Pearson, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1, outlier.shape = NA) +
  scale_fill_manual(values=c("#FF0000", "#D3D3D3", "#0000FF"))
dev.off()
null device 
          1 
# Save outputs
save(pearson_ttest_cocl2_firstvsrand, pearson_ttest_cocl2_secondvsfirst, pearson_ttest_cocl2_secondvsrand, pearson_ttest_cocl2_randvsrand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_values.RData')
rm(pearson_ttest_cocl2_firstvsrand, pearson_ttest_cocl2_secondvsfirst, pearson_ttest_cocl2_secondvsrand, pearson_ttest_cocl2_randvsrand)

save(plotting_df_pearson_cocl2, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cocl2_pearson_plotting_df.RData')
rm(plotting_df_pearson_cocl2)

Statistical analysis and plotting of pearson metrics - cis

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_results.RData') # Load data

pearson_ttest_dabtram_firstvsrand <- t.test(dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand,  paired = F)
pearson_ttest_dabtram_secondvsrand <- t.test(dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand,  paired = F)
pearson_ttest_dabtram_secondvsfirst <- t.test(dabtram_second_pearson_filt, dabtram_first_pearson_filt,  paired = F)
pearson_ttest_dabtram_randvsrand <- t.test(dabtram_second_pearson_filt_rand, dabtram_first_pearson_filt_rand,  paired = F)

rm(dabtram_first_pearson, dabtram_first_pearson_rand, dabtram_first_subset, dabtram_first_subset_rand, dabtram_second_pearson, dabtram_second_pearson_rand, dabtram_second_subset, dabtram_second_subset_rand)

plotting_df_pearson_dabtram <- data.frame(Grouping = c(rep('first',length(dabtram_first_pearson_filt)), rep('random',length(dabtram_first_pearson_filt)), rep('second', length(dabtram_second_pearson_filt)), rep('random', length(dabtram_second_pearson_filt))),
                          Pearson = c(dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand),
                          Treatment = c(rep('dabtram first',length(dabtram_first_pearson_filt)), rep('dabtram first rand', length(dabtram_first_pearson_filt_rand)),rep('dabtram second',length(dabtram_second_pearson_filt)),rep('dabtram second rand',length(dabtram_second_pearson_filt_rand))))
colnames(plotting_df_pearson_dabtram) <- c('Grouping','Pearson','Treatment')

rm(dabtram_first_pearson_filt, dabtram_first_pearson_filt_rand, dabtram_second_pearson_filt, dabtram_second_pearson_filt_rand)
gc()
             used    (Mb)  gc trigger    (Mb) limit (Mb)    max used    (Mb)
Ncells    4102712   219.2     6815804   364.1         NA     6815804   364.1
Vcells 3678842165 28067.4 11389246976 86893.1     102400 11361287181 86679.8
pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_plot_subsampled.pdf')
set.seed(1)
ggplot(plotting_df_pearson_dabtram[sample(1:nrow(plotting_df_pearson_dabtram), 10000000),], aes(x = Treatment, y = Pearson, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1, outlier.shape = NA) +
  scale_fill_manual(values=c("#FF0000", "#D3D3D3", "#0000FF"))
dev.off()
null device 
          1 
# Save outputs
save(pearson_ttest_dabtram_firstvsrand, pearson_ttest_dabtram_secondvsfirst, pearson_ttest_dabtram_secondvsrand,pearson_ttest_dabtram_randvsrand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_values.RData')
rm(pearson_ttest_dabtram_firstvsrand, pearson_ttest_dabtram_secondvsfirst, pearson_ttest_dabtram_secondvsrand, pearson_ttest_dabtram_randvsrand)

save(plotting_df_pearson_dabtram, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/dabtram_pearson_plotting_df.RData')
rm(plotting_df_pearson_dabtram)

Load in the ttest data and compile into excel sheet

load('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_results.RData') # Load data

pearson_ttest_cis_firstvsrand <- t.test(cis_first_pearson_filt, cis_first_pearson_filt_rand,  paired = F)
pearson_ttest_cis_secondvsrand <- t.test(cis_second_pearson_filt, cis_second_pearson_filt_rand,  paired = F)
pearson_ttest_cis_secondvsfirst <- t.test(cis_second_pearson_filt, cis_first_pearson_filt,  paired = F)
pearson_ttest_cis_randvsrand <- t.test(cis_second_pearson_filt_rand, cis_first_pearson_filt_rand,  paired = F)

rm(cis_first_pearson, cis_first_pearson_rand, cis_first_subset, cis_first_subset_rand, cis_second_pearson, cis_second_pearson_rand, cis_second_subset, cis_second_subset_rand)

plotting_df_pearson_cis <- data.frame(Grouping = c(rep('first',length(cis_first_pearson_filt)), rep('random',length(cis_first_pearson_filt)), rep('second', length(cis_second_pearson_filt)), rep('random', length(cis_second_pearson_filt))),
                          Pearson = c(cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand),
                          Treatment = c(rep('cis first',length(cis_first_pearson_filt)), rep('cis first rand', length(cis_first_pearson_filt_rand)),rep('cis second',length(cis_second_pearson_filt)),rep('cis second rand',length(cis_second_pearson_filt_rand))))
colnames(plotting_df_pearson_cis) <- c('Grouping','Pearson','Treatment')

rm(cis_first_pearson_filt, cis_first_pearson_filt_rand, cis_second_pearson_filt, cis_second_pearson_filt_rand)
gc()
             used    (Mb) gc trigger    (Mb) limit (Mb)    max used    (Mb)
Ncells    4102791   219.2    6815804   364.1         NA     6815804   364.1
Vcells 2804429888 21396.2 9111397581 69514.5     102400 11361287181 86679.8
pdf('2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_plot_subsampled.pdf')
set.seed(1)
ggplot(plotting_df_pearson_cis[sample(1:nrow(plotting_df_pearson_cis), 10000000),], aes(x = Treatment, y = Pearson, fill = Grouping)) + geom_violin() + geom_boxplot(width = 0.1, outlier.shape = NA) +
  scale_fill_manual(values=c("#FF0000", "#D3D3D3", "#0000FF"))
dev.off()
null device 
          1 
# Save outputs
save(pearson_ttest_cis_firstvsrand, pearson_ttest_cis_secondvsfirst, pearson_ttest_cis_secondvsrand, pearson_ttest_cis_randvsrand, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_values.RData')
rm(pearson_ttest_cis_firstvsrand, pearson_ttest_cis_secondvsfirst, pearson_ttest_cis_secondvsrand, pearson_ttest_cis_randvsrand)

save(plotting_df_pearson_cis, file = '2022_01_14_analysis_scripts/2022_05_27_analysis/Condition_Clustering/cis_pearson_plotting_df.RData')
rm(plotting_df_pearson_cis)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQojSU1QT1JUQU5UIE5PVEU6IGV2ZXJ5dGhpbmcgZm9yIHBsb3R0aW5nIGluIGZpZ3VyZXMgY3VycmVudGx5IGNvbWVzIGZyb20gdGhlIHNlY29uZF90aW1lcG9pbnQgb2JqZWN0LCBidXQgdGhlcmUgYXJlIGFkZGl0aW9uYWwgY2h1bmtzIHRoYXQgcnVuIHNpbWlsYXIgYW5hbHlzZXMgb24gYWxsX2RhdGEgb2JqZWN0cyB3aXRoIGRpZmZlcmVudCBjbHVzdGVyIG51bWJlcnMKCgojU2V0IHdvcmtpbmcgZGlyZWN0b3J5IHRvIGFwcHJvcHJpYXRlIGZvbGRlciBmb3IgaW5wdXRzIGFuZCBvdXRwdXRzIG9uIEdvb2dsZSBEcml2ZQpgYGB7ciwgc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiNrbml0cjo6b3B0c19rbml0JHNldChyb290LmRpciA9ICcvVm9sdW1lcy9Hb29nbGVEcml2ZS9NeSBEcml2ZS9GYXNzZV9TaGFyZWQvQUpGX0RyaXZlX2NvcHkvRXhwZXJpbWVudHMvQUpGMDA5JykgIyBmb3IgYXJpYSdzIGNvbXB1dGVyCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gJy9Vc2Vycy9keWxhbnNjaGFmZi9MaWJyYXJ5L0Nsb3VkU3RvcmFnZS9Hb29nbGVEcml2ZS1keXNjaGFmZkBzeWRzaGFmZmVybGFiLmNvbS8uc2hvcnRjdXQtdGFyZ2V0cy1ieS1pZC8xelNxeDNJelhNd3Q2Y2xVand5cW1sT2Y0RzFLNTNsdnkvRmFzc2VfU2hhcmVkL0FKRl9Ecml2ZV9jb3B5L0V4cGVyaW1lbnRzL0FKRjAwOScpICMgZm9yIGR5bGFuJ3MgY29tcHV0ZXIKCiMyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy8gaXMgYWRkaXRpb25hbCBwYXRoIGZvciBvdXRwdXRzCgpgYGAKCiNJbml0aWFsaXplCmBgYHtyIGluY2x1ZGUgPSBGQUxTRX0Kcm0obGlzdCA9IGxzKCkpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQpsaWJyYXJ5KHhsc3gpCmBgYAoKIyBMb2FkIGRhdGEKYGBge3J9CmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL1ByZXByb2Nlc3NfR0VYL09iamVjdHNfcHJlbWVyZ2VkLlJEYXRhJykKbG9hZCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvUHJlcHJvY2Vzc19HRVgvc2Vjb25kX3RpbWVwb2ludF9tZXJnZWQuUkRhdGEnKQpsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9QcmVwcm9jZXNzX0dFWC9maXJzdF90aW1lcG9pbnRfbWVyZ2VkLlJEYXRhJykKYGBgCgojIGNsdXN0ZXIgc2Vjb25kIHRpbWVwb2ludCBhbmQgcGxvdApgYGB7cn0Kc2Vjb25kX3RpbWVwb2ludCA8LSBOb3JtYWxpemVEYXRhKHNlY29uZF90aW1lcG9pbnQpCnNlY29uZF90aW1lcG9pbnQgPC0gRmluZFZhcmlhYmxlRmVhdHVyZXMoc2Vjb25kX3RpbWVwb2ludCwgc2VsZWN0aW9uLm1ldGhvZCA9ICd2c3QnLCBuRmVhdHVyZXMgPSAyMDAwMCkKc2Vjb25kX3RpbWVwb2ludCA8LSBTY2FsZURhdGEoc2Vjb25kX3RpbWVwb2ludCkKc2Vjb25kX3RpbWVwb2ludCA8LSBSdW5QQ0Eoc2Vjb25kX3RpbWVwb2ludCkKc2Vjb25kX3RpbWVwb2ludCA8LSBGaW5kTmVpZ2hib3JzKHNlY29uZF90aW1lcG9pbnQsIGRpbXMgPSAxOjE1KQpzZWNvbmRfdGltZXBvaW50IDwtIEZpbmRDbHVzdGVycyhzZWNvbmRfdGltZXBvaW50LCByZXNvbHV0aW9uID0gMC41KQpzZWNvbmRfdGltZXBvaW50IDwtIFJ1blVNQVAoc2Vjb25kX3RpbWVwb2ludCwgZGltcyA9IDE6MTUpCgpjZWxsc19wZXJfY2x1c3RlciA8LSBkYXRhLmZyYW1lIChDbHVzdGVyID0gYXMubnVtZXJpYyhzZWNvbmRfdGltZXBvaW50JHNldXJhdF9jbHVzdGVycyksIENvbmRpdGlvbiA9IHNlY29uZF90aW1lcG9pbnQkT0dfY29uZGl0aW9uKQpjZWxsc19wZXJfY2x1c3Rlcl9saXN0IDwtIGxpc3QoKQoKcGRmKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9vcmlnaW5hbF9jb25kaXRpb25fc2Vjb25kX3RpbWVwb2ludC5wZGYnKQpwcmludChEaW1QbG90KHNlY29uZF90aW1lcG9pbnQpKQpwcmludChEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIGxhYmVsID0gVCwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgY29scyA9IGMoJ2RhYnRyYW10b2RhYnRyYW0nID0gJyM1NjFFNTknLCAnZGFidHJhbXRvY29jbDInID0gJyNBMjI0OEUnLCAnZGFidHJhbXRvY2lzJyA9ICcjOUQ4NUJFJywgJ2NvY2wydG9kYWJ0cmFtJyA9ICcjMTA0MTNCJywgJ2NvY2wydG9jb2NsMicgPSAnIzZBQkQ0NScsICdjb2NsMnRvY2lzJyA9ICcjNkRDNDlDJywgJ2Npc3RvZGFidHJhbScgPSAnI0EyMzYyMicsICdjaXN0b2NvY2wyJyA9ICcjRjQ5MTI5JywgJ2Npc3RvY2lzJyA9ICcjRkJEMDhDJykpKQoKZm9yIChpIGluIDE6KG1heChjZWxsc19wZXJfY2x1c3RlciRDbHVzdGVyKSkpewogIGN1cnJlbnRjbHVzdGVyIDwtIGZpbHRlcihjZWxsc19wZXJfY2x1c3RlciwgY2VsbHNfcGVyX2NsdXN0ZXIkQ2x1c3RlciA9PSBpKQogIGNlbGxzX3Blcl9jbHVzdGVyX2xpc3RbW3Bhc3RlMCgnQ2x1c3RlcicsIGkpXV0gPC0gZGF0YS5mcmFtZSh0YWJsZShjdXJyZW50Y2x1c3RlciRDb25kaXRpb24pKQogIAogIHByaW50KGdncGxvdChjZWxsc19wZXJfY2x1c3Rlcl9saXN0W1twYXN0ZTAoJ0NsdXN0ZXInLCBpKV1dLCBhZXMoeCA9JycsIHkgPSBGcmVxLCBmaWxsID0gVmFyMSkpICsgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgY29vcmRfcG9sYXIoJ3knLCBzdGFydCA9IDApICsgdGhlbWVfdm9pZCgpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygnZGFidHJhbXRvZGFidHJhbScgPSAnIzU2MUU1OScsICdkYWJ0cmFtdG9jb2NsMicgPSAnI0EyMjQ4RScsICdkYWJ0cmFtdG9jaXMnID0gJyM5RDg1QkUnLCAnY29jbDJ0b2RhYnRyYW0nID0gJyMxMDQxM0InLCAnY29jbDJ0b2NvY2wyJyA9ICcjNkFCRDQ1JywgJ2NvY2wydG9jaXMnID0gJyM2REM0OUMnLCAnY2lzdG9kYWJ0cmFtJyA9ICcjQTIzNjIyJywgJ2Npc3RvY29jbDInID0gJyNGNDkxMjknLCAnY2lzdG9jaXMnID0gJyNGQkQwOEMnKSkgKyBsYWJzKHRpdGxlID0gcGFzdGUoJ09yaWdpbmFsIGNvbmRpdGlvbiBvZiBjZWxscyBpbiBjbHVzdGVyJywgaS0xKSkpCn0KZGV2Lm9mZigpCgpgYGAKCiMgVGhpcyBpcyB0aGUgc2FtZSBjaHVuayBhcyBhYm92ZSBidXQgaXQgbWFrZXMgdGhlIHBsb3RzIGFzIGJhciBjaGFydHMgaW4gaW5kaXZpZHVhbCBQREZzIGZvciBwdWxsaW5nIGludG8gaWxsdXN0cmF0b3IKYGBge3J9CgpjZWxsc19wZXJfY2x1c3RlciA8LSBkYXRhLmZyYW1lIChDbHVzdGVyID0gYXMubnVtZXJpYyhzZWNvbmRfdGltZXBvaW50JHNldXJhdF9jbHVzdGVycyksIENvbmRpdGlvbiA9IHNlY29uZF90aW1lcG9pbnQkT0dfY29uZGl0aW9uKQpjZWxsc19wZXJfY2x1c3Rlcl9saXN0IDwtIGxpc3QoKQoKZm9yIChpIGluIDE6KG1heChjZWxsc19wZXJfY2x1c3RlciRDbHVzdGVyKSkpewogIHBkZihwYXN0ZTAoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL29yaWdpbmFsX2NvbmRpdGlvbl9zZWNvbmRfdGltZXBvaW50X2NsdXN0ZXInLCBpLTEsICcucGRmJykpCiAgY3VycmVudGNsdXN0ZXIgPC0gZmlsdGVyKGNlbGxzX3Blcl9jbHVzdGVyLCBjZWxsc19wZXJfY2x1c3RlciRDbHVzdGVyID09IGkpCiAgY2VsbHNfcGVyX2NsdXN0ZXJfbGlzdFtbcGFzdGUwKCdDbHVzdGVyJywgaSldXSA8LSBkYXRhLmZyYW1lKHRhYmxlKGN1cnJlbnRjbHVzdGVyJENvbmRpdGlvbikpCiAgCiAgcHJpbnQoZ2dwbG90KGNlbGxzX3Blcl9jbHVzdGVyX2xpc3RbW3Bhc3RlMCgnQ2x1c3RlcicsIGkpXV0sIGFlcyh4ID0nJywgeSA9IEZyZXEsIGZpbGwgPSBWYXIxKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICdmaWxsJywgc3RhdCA9ICdpZGVudGl0eScpICsgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygnZGFidHJhbScgPSAnIzYyMzU5NCcsICdjb2NsMicgPSAnIzBGODI0MScsICdjaXMnID0gJyNDOTZEMjknLCAnZGFidHJhbXRvZGFidHJhbScgPSAnIzU2MUU1OScsICdkYWJ0cmFtdG9jb2NsMicgPSAnI0EyMjQ4RScsICdkYWJ0cmFtdG9jaXMnID0gJyM5RDg1QkUnLCAnY29jbDJ0b2RhYnRyYW0nID0gJyMxMDQxM0InLCAnY29jbDJ0b2NvY2wyJyA9ICcjNkFCRDQ1JywgJ2NvY2wydG9jaXMnID0gJyM2REM0OUMnLCAnY2lzdG9kYWJ0cmFtJyA9ICcjQTIzNjIyJywgJ2Npc3RvY29jbDInID0gJyNGNDkxMjknLCAnY2lzdG9jaXMnID0gJyNGQkQwOEMnKSkgKyBsYWJzKHRpdGxlID0gcGFzdGUoJ09yaWdpbmFsIGNvbmRpdGlvbiBvZiBjZWxscyBpbiBzZWNvbmQgdGltZXBvaW50IGNsdXN0ZXInLCBpLTEpKSkKICBkZXYub2ZmKCkKfQpgYGAKCiNlZGl0aW5nIGNlbGxzX3Blcl9jbHVzdGVyIHNvIHRoYXQgdGhlIGNvbmRpdGlvbiBuYW1lIGlzIHdoYXRldmVyIHNlY29uZCBjb25kaXRpb24KYGBge3IgaW5jbHVkZSA9IEZBTFNFfQoKY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZyA8LSBjZWxsc19wZXJfY2x1c3RlcgpjZWxsc19wZXJfY2x1c3Rlcl9maXJzdGRydWcgPC0gY2VsbHNfcGVyX2NsdXN0ZXIKCmZvciAoaSBpbiAxOm5yb3coY2VsbHNfcGVyX2NsdXN0ZXIpKXsKICBpZiAoY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImRhYnRyYW10b2RhYnRyYW0iIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjaXN0b2RhYnRyYW0iIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjb2NsMnRvZGFidHJhbSIpIHsKICAgIGNlbGxzX3Blcl9jbHVzdGVyX3NlY29uZGRydWckQ29uZGl0aW9uW1tpXV0gPC0gImRhYnRyYW1zZWNvbmQiCiAgfQogIGlmIChjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY29jbDJ0b2NvY2wyIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY2lzdG9jb2NsMiIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImRhYnRyYW10b2NvY2wyIikgewogICAgY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZyRDb25kaXRpb25bW2ldXSA8LSAiY29jbDJzZWNvbmQiCiAgfQogIGlmIChjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY2lzdG9jaXMiIHx8IGNlbGxzX3Blcl9jbHVzdGVyJENvbmRpdGlvbltbaV1dID09ICJjb2NsMnRvY2lzIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiZGFidHJhbXRvY2lzIikgewogICAgY2VsbHNfcGVyX2NsdXN0ZXJfc2Vjb25kZHJ1ZyRDb25kaXRpb25bW2ldXSA8LSAiY2lzc2Vjb25kIgogIH0KfQoKZm9yIChpIGluIDE6bnJvdyhjZWxsc19wZXJfY2x1c3RlcikpewogIGlmIChjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiZGFidHJhbXRvZGFidHJhbSIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImRhYnRyYW10b2NpcyIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImRhYnRyYW10b2NvY2wyIikgewogICAgY2VsbHNfcGVyX2NsdXN0ZXJfZmlyc3RkcnVnJENvbmRpdGlvbltbaV1dIDwtICJkYWJ0cmFtZmlyc3QiCiAgfQogIGlmIChjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY29jbDJ0b2NvY2wyIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY29jbDJ0b2NpcyIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImNvY2wydG9kYWJ0cmFtIikgewogICAgY2VsbHNfcGVyX2NsdXN0ZXJfZmlyc3RkcnVnJENvbmRpdGlvbltbaV1dIDwtICJjb2NsMmZpcnN0IgogIH0KICBpZiAoY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImNpc3RvY2lzIiB8fCBjZWxsc19wZXJfY2x1c3RlciRDb25kaXRpb25bW2ldXSA9PSAiY2lzdG9jb2NsMiIgfHwgY2VsbHNfcGVyX2NsdXN0ZXIkQ29uZGl0aW9uW1tpXV0gPT0gImNpc3RvZGFidHJhbSIpIHsKICAgIGNlbGxzX3Blcl9jbHVzdGVyX2ZpcnN0ZHJ1ZyRDb25kaXRpb25bW2ldXSA8LSAiY2lzZmlyc3QiCiAgfQp9Cgojbm93IGNvbG9yZWQgYmFzZWQgb24gc2Vjb25kIGRydWcgb25seQpmb3IgKGkgaW4gMToobWF4KGNlbGxzX3Blcl9jbHVzdGVyX3NlY29uZGRydWckQ2x1c3RlcikpKXsKICBwZGYocGFzdGUwKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9lbmRfY29uZGl0aW9uX3NlY29uZF90aW1lcG9pbnQnLCBpLTEsICcucGRmJykpCiAgY3VycmVudGNsdXN0ZXIgPC0gZmlsdGVyKGNlbGxzX3Blcl9jbHVzdGVyX3NlY29uZGRydWcsIGNlbGxzX3Blcl9jbHVzdGVyX3NlY29uZGRydWckQ2x1c3RlciA9PSBpKQogIGNlbGxzX3Blcl9jbHVzdGVyX2xpc3RbW3Bhc3RlMCgnQ2x1c3RlcicsIGkpXV0gPC0gZGF0YS5mcmFtZSh0YWJsZShjdXJyZW50Y2x1c3RlciRDb25kaXRpb24pKQogIAogIHByaW50KGdncGxvdChjZWxsc19wZXJfY2x1c3Rlcl9saXN0W1twYXN0ZTAoJ0NsdXN0ZXInLCBpKV1dLCBhZXMoeCA9JycsIHkgPSBGcmVxLCBmaWxsID0gVmFyMSkpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAnZmlsbCcsIHN0YXQgPSAnaWRlbnRpdHknKSArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoJ2RhYnRyYW1zZWNvbmQnID0gJyM2MjM1OTQnLCAnY29jbDJzZWNvbmQnID0gJyMwRjgyNDEnLCAnY2lzc2Vjb25kJyA9ICcjQzk2RDI5JykpICsgbGFicyh0aXRsZSA9IHBhc3RlKCdFbmQgY29uZGl0aW9uIG9mIGNlbGxzIGluIHNlY29uZCB0aW1lcG9pbnQgY2x1c3RlcicsIGktMSkpKQogIGRldi5vZmYoKQp9Cgojbm93IGNvbG9yZWQgYmFzZWQgb24gZmlyc3QgZHJ1ZyBvbmx5CmZvciAoaSBpbiAxOihtYXgoY2VsbHNfcGVyX2NsdXN0ZXJfZmlyc3RkcnVnJENsdXN0ZXIpKSl7CiAgcGRmKHBhc3RlMCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvZmlyc3RfY29uZGl0aW9uX3NlY29uZF90aW1lcG9pbnQnLCBpLTEsICcucGRmJykpCiAgY3VycmVudGNsdXN0ZXIgPC0gZmlsdGVyKGNlbGxzX3Blcl9jbHVzdGVyX2ZpcnN0ZHJ1ZywgY2VsbHNfcGVyX2NsdXN0ZXJfZmlyc3RkcnVnJENsdXN0ZXIgPT0gaSkKICBjZWxsc19wZXJfY2x1c3Rlcl9saXN0W1twYXN0ZTAoJ0NsdXN0ZXInLCBpKV1dIDwtIGRhdGEuZnJhbWUodGFibGUoY3VycmVudGNsdXN0ZXIkQ29uZGl0aW9uKSkKICAKICBwcmludChnZ3Bsb3QoY2VsbHNfcGVyX2NsdXN0ZXJfbGlzdFtbcGFzdGUwKCdDbHVzdGVyJywgaSldXSwgYWVzKHggPScnLCB5ID0gRnJlcSwgZmlsbCA9IFZhcjEpKSArIGdlb21fYmFyKHBvc2l0aW9uID0gJ2ZpbGwnLCBzdGF0ID0gJ2lkZW50aXR5JykgKyBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCdkYWJ0cmFtZmlyc3QnID0gJyM2MjM1OTQnLCAnY29jbDJmaXJzdCcgPSAnIzBGODI0MScsICdjaXNmaXJzdCcgPSAnI0M5NkQyOScpKSArIGxhYnModGl0bGUgPSBwYXN0ZSgnRW5kIGNvbmRpdGlvbiBvZiBjZWxscyBpbiBmaXJzdCB0aW1lcG9pbnQgY2x1c3RlcicsIGktMSkpKQogIGRldi5vZmYoKQp9CmBgYAoKI1VNQVBzIGhpZ2hsaWdodGluZyBhbGwgY2VsbHMgdGhhdCBoYWQgc2FtZSBmaXJzdCBhbmQgc2Vjb25kIGRydWcgaW4gc2Vjb25kX3RpbWVwb2ludCBvYmplY3QKYGBge3J9CmNlbGxzX3Blcl9jb25kaXRpb24gPC0gbGlzdCgpCmZvciAoaSBpbiBjKCdkYWJ0cmFtdG9kYWJ0cmFtJywgJ2RhYnRyYW10b2NvY2wyJywgJ2RhYnRyYW10b2NpcycsICdjb2NsMnRvZGFidHJhbScsICdjb2NsMnRvY29jbDInLCAnY29jbDJ0b2NpcycsICdjaXN0b2RhYnRyYW0nLCAnY2lzdG9jb2NsMicsICdjaXN0b2NpcycpKXsKICBjZWxsc19wZXJfY29uZGl0aW9uW1twYXN0ZTAoaSwgJ19jZWxscycpXV0gPC0gbmFtZXMoc2Vjb25kX3RpbWVwb2ludCRvcmlnLmlkZW50W3NlY29uZF90aW1lcG9pbnQkT0dfY29uZGl0aW9uID09IGldKQp9CgpwZGYoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RydWdfZ3JvdXBfaGlnaGxpZ2h0cy5wZGYnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY29jbDJfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCdyZWQnKSkgKyBnZ3RpdGxlKCdkYWJ0cmFtIGZpcnN0IGNlbGxzJykKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2RhYnRyYW1fY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCdyZWQnKSkgKyBnZ3RpdGxlKCdjb2NsMiBmaXJzdCBjZWxscycpCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNpc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ3JlZCcpKSArIGdndGl0bGUoJ2NpcyBmaXJzdCBjZWxscycpCgpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ2JsdWUnKSkgKyBnZ3RpdGxlKCdkYWJ0cmFtIHNlY29uZCBjZWxscycpCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2NvY2wyX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnYmx1ZScpKSArIGdndGl0bGUoJ2NvY2wyIHNlY29uZCBjZWxscycpCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNpc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2Npc19jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ2JsdWUnKSkgKyBnZ3RpdGxlKCdjaXMgc2Vjb25kIGNlbGxzJykKCmRldi5vZmYoKQpgYGAKCiNVTUFQcyBoaWdobGlnaHRpbmcgYWxsIGNlbGxzIHRoYXQgaGFkIHNhbWUgZmlyc3QgZHJ1ZyBpbiBmaXJzdF90aW1lcG9pbnQgb2JqZWN0CmBgYHtyfQpwZGYoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2RydWdfZ3JvdXBfaGlnaGxpZ2h0c19maXJzdF90aW1lcG9pbnQucGRmJykKCkRpbVBsb3QoZmlyc3RfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gIk9HX2NvbmRpdGlvbiIsIHB0LnNpemUgPSAyLCBjb2xzID0gIGMoJ2RhYnRyYW0nID0gJyM2MjM1OTQnLCAnY29jbDInID0gJyMwRjgyNDEnLCAnY2lzJyA9ICcjQzk2RDI5JykpCkRpbVBsb3QoZmlyc3RfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KG5hbWVzKGZpcnN0X3RpbWVwb2ludCRvcmlnLmlkZW50W2ZpcnN0X3RpbWVwb2ludCRPR19jb25kaXRpb24gPT0gJ2RhYnRyYW0nXSkpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCdyZWQnKSkgKyBnZ3RpdGxlKCdkYWJ0cmFtIGZpcnN0IGNlbGxzJykKRGltUGxvdChmaXJzdF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QobmFtZXMoZmlyc3RfdGltZXBvaW50JG9yaWcuaWRlbnRbZmlyc3RfdGltZXBvaW50JE9HX2NvbmRpdGlvbiA9PSAnY29jbDInXSkpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gKCdyZWQnKSkgKyBnZ3RpdGxlKCdjb2NsMiBmaXJzdCBjZWxscycpCkRpbVBsb3QoZmlyc3RfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KG5hbWVzKGZpcnN0X3RpbWVwb2ludCRvcmlnLmlkZW50W2ZpcnN0X3RpbWVwb2ludCRPR19jb25kaXRpb24gPT0gJ2NpcyddKSksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJ3JlZCcpKSArIGdndGl0bGUoJ2NpcyBmaXJzdCBjZWxscycpCgpGZWF0dXJlUGxvdChmaXJzdF90aW1lcG9pbnQsIGZlYXR1cmVzID0gJ0VHRlInLCBwdC5zaXplID0gMikgKwogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oY29sb3JzID0gcmV2KGJyZXdlci5wYWwobiA9IDExLCBuYW1lID0gJ1JkQnUnKSkpCkZlYXR1cmVQbG90KGZpcnN0X3RpbWVwb2ludCwgZmVhdHVyZXMgPSAnTkdGUicsIHB0LnNpemUgPSAyKSArCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50bihjb2xvcnMgPSByZXYoYnJld2VyLnBhbChuID0gMTEsIG5hbWUgPSAnUmRCdScpKSkKCgpkZXYub2ZmKCkKYGBgCgojTW9yZSBwbG90cyBub3QgaW4gUERGIGJ1dCBqdXN0IGZvciBxdWljayB2aXN1YWxpemF0aW9ucwpgYGB7cn0KRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY29jbDJfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gYygnI2EyMjQ4ZScsICcjOWQ4NWJlJywgJyM1NjFlNTknKSkgKyBnZ3RpdGxlKCdkYWJ0cmFtIGZpcnN0IGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2RhYnRyYW1fY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2NvY2wyX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnIzYyMzU5NCcpKSArIGdndGl0bGUoJ2RhYnRyYW0gZmlyc3QgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kZGFidHJhbXRvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2RhYnRyYW1fY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2RhYnRyYW1fY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gYygnIzEwNDEzYicsICcjYTIzNjIyJywgJyM1NjFlNTknKSkgKyBnZ3RpdGxlKCdkYWJ0cmFtIHNlY29uZCBjZWxscycpCgpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9kYWJ0cmFtX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvZGFidHJhbV9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJyM2MjM1OTQnKSkgKyBnZ3RpdGxlKCdkYWJ0cmFtIHNlY29uZCBjZWxscycpCgpgYGAKCmBgYHtyfQpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvZGFidHJhbV9jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSBjKCcjMTA0MTNiJywgJyM2ZGM0OWMnLCAnIzZhYmQ0NScpKSArIGdndGl0bGUoJ2NvY2wyIGZpcnN0IGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9kYWJ0cmFtX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnIzBmODI0MScpKSArIGdndGl0bGUoJ2NvY2wyIGZpcnN0IGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2NvY2wyX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9IGMoJyNhMjI0OGUnLCAnI2Y0OTEyOScsICcjNmFiZDQ1JykpICsgZ2d0aXRsZSgnY29jbDIgc2Vjb25kIGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNvY2wydG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2NvY2wyX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2NvY2wyX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnIzBmODI0MScpKSArIGdndGl0bGUoJ2NvY2wyIHNlY29uZCBjZWxscycpCgpgYGAKCmBgYHtyfQpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9jb2NsMl9jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2RhYnRyYW1fY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gYygnI2EyMzYyMicsICcjZjQ5MTI5JywgJyNmYmQwOGMnKSkgKyBnZ3RpdGxlKCdjaXMgZmlyc3QgY2VsbHMnKQoKRGltUGxvdChzZWNvbmRfdGltZXBvaW50LCByZWR1Y3Rpb24gPSAidW1hcCIsIGRpbXMgPSBjKDEsMiksIGdyb3VwLmJ5ID0gJ09HX2NvbmRpdGlvbicsIHB0LnNpemUgPSAuMSwKICAgICAgICBjZWxscy5oaWdobGlnaHQgPSBsaXN0KGNlbGxzX3Blcl9jb25kaXRpb24kY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGNpc3RvY29jbDJfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9kYWJ0cmFtX2NlbGxzKSwKICAgICAgICBjb2xzLmhpZ2hsaWdodCA9ICgnI2M5NmQyOScpKSArIGdndGl0bGUoJ2NpcyBmaXJzdCBjZWxscycpCgpEaW1QbG90KHNlY29uZF90aW1lcG9pbnQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZGltcyA9IGMoMSwyKSwgZ3JvdXAuYnkgPSAnT0dfY29uZGl0aW9uJywgcHQuc2l6ZSA9IC4xLAogICAgICAgIGNlbGxzLmhpZ2hsaWdodCA9IGxpc3QoY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY2lzdG9jaXNfY2VsbHMsIGNlbGxzX3Blcl9jb25kaXRpb24kY29jbDJ0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRkYWJ0cmFtdG9jaXNfY2VsbHMpLAogICAgICAgIGNvbHMuaGlnaGxpZ2h0ID0gYygnIzlkODViZScsICcjNmRjNDljJywgJyNmYmQwOGMnKSkgKyBnZ3RpdGxlKCdjaXMgc2Vjb25kIGNlbGxzJykKCkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCwgcmVkdWN0aW9uID0gInVtYXAiLCBkaW1zID0gYygxLDIpLCBncm91cC5ieSA9ICdPR19jb25kaXRpb24nLCBwdC5zaXplID0gLjEsCiAgICAgICAgY2VsbHMuaGlnaGxpZ2h0ID0gbGlzdChjZWxsc19wZXJfY29uZGl0aW9uJGNpc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjaXN0b2Npc19jZWxscywgY2VsbHNfcGVyX2NvbmRpdGlvbiRjb2NsMnRvY2lzX2NlbGxzLCBjZWxsc19wZXJfY29uZGl0aW9uJGRhYnRyYW10b2Npc19jZWxscyksCiAgICAgICAgY29scy5oaWdobGlnaHQgPSAoJyNjOTZkMjknKSkgKyBnZ3RpdGxlKCdjaXMgc2Vjb25kIGNlbGxzJykKCmBgYAoKIyBTYXZlIHRoZSBvYmplY3QgdG8gbG9hZCBpbiBmb3IgZGlzdGFuY2UgbWV0cmljcwpgYGB7cn0Kc2F2ZS5pbWFnZSgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvd29ya3NwYWNlLlJEYXRhJykKYGBgCgojIFJ1biBkaXN0YW5jZSBtZXRyaWNzCmBgYHtyfQojIERlZmluZSBtYW5oYXR0ZW4gZGlzdGFuY2UgZnVuY3Rpb24KbWFuaGF0dGFuLmRpc3RhbmNlIDwtIGZ1bmN0aW9uKHgsIHkpIHJldHVybihzdW0oYWJzKHgteSkpKQoKIyBNYWtlIG1ldGFkYXRhIG9iamVjdHMgb2YgdGhlIGZpcnN0IGFuZCBzZWNvbmQgY29uZGl0aW9ucwpzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudCA8LSBzYXBwbHkoc3Ryc3BsaXQoc2Vjb25kX3RpbWVwb2ludCRPR19jb25kaXRpb24sICJ0byIpLCAiW1siLCAxKQpzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQgPC0gc2FwcGx5KHN0cnNwbGl0KHNlY29uZF90aW1lcG9pbnQkT0dfY29uZGl0aW9uLCAidG8iKSwgIltbIiwgMikKCiMgR2V0IGlucHV0IGRhdGEgYW5kIHN1YmVzdAppbnB1dF9kYXRhIDwtIEdldEFzc2F5RGF0YShzZWNvbmRfdGltZXBvaW50LCBhc3NheSA9ICdSTkEnLCBzbG90ID0gJ3NjYWxlLmRhdGEnKQoKIyBOdW1iZXIgb2YgY2VsbHMgZm9yIHN1YnNldHRpbmcKbnVtX2NlbGxzIDwtIDEwMDAwCgojIExvb2sgYXQgZ3JvdXBpbmcgYmFzZWQgb24gZmlyc3Qgc2FtcGxlCklkZW50cyhzZWNvbmRfdGltZXBvaW50KSA8LSBzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudApEaW1QbG90KHNlY29uZF90aW1lcG9pbnQpCgpjb2NsMl9maXJzdF9jZWxscyA8LSAgc2FtcGxlKG5hbWVzKHNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudCA9PSAnY29jbDInXSwgbnVtX2NlbGxzKQpjb2NsMl9maXJzdF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY29jbDJfZmlyc3RfY2VsbHNdCmNvY2wyX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSA8LSBDdXN0b21EaXN0YW5jZShjb2NsMl9maXJzdF9zdWJzZXQsIG1hbmhhdHRhbi5kaXN0YW5jZSkKCmRhYnRyYW1fZmlyc3RfY2VsbHMgPC0gIHNhbXBsZShuYW1lcyhzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQgPT0gJ2RhYnRyYW0nXSwgbnVtX2NlbGxzKQpkYWJ0cmFtX2ZpcnN0X3N1YnNldCA8LSBpbnB1dF9kYXRhWyxkYWJ0cmFtX2ZpcnN0X2NlbGxzXQpkYWJ0cmFtX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSA8LSBDdXN0b21EaXN0YW5jZShkYWJ0cmFtX2ZpcnN0X3N1YnNldCwgbWFuaGF0dGFuLmRpc3RhbmNlKQoKY2lzX2ZpcnN0X2NlbGxzIDwtICBzYW1wbGUobmFtZXMoc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50ID09ICdjaXMnXSwgbnVtX2NlbGxzKQpjaXNfZmlyc3Rfc3Vic2V0IDwtIGlucHV0X2RhdGFbLGNpc19maXJzdF9jZWxsc10KY2lzX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSA8LSBDdXN0b21EaXN0YW5jZShjaXNfZmlyc3Rfc3Vic2V0LCBtYW5oYXR0YW4uZGlzdGFuY2UpCgpJZGVudHMoc2Vjb25kX3RpbWVwb2ludCkgPC0gc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50CkRpbVBsb3Qoc2Vjb25kX3RpbWVwb2ludCkKCmNvY2wyX3NlY29uZF9jZWxscyA8LSAgc2FtcGxlKG5hbWVzKHNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50ID09ICdjb2NsMiddLCBudW1fY2VsbHMpCmNvY2wyX3NlY29uZF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY29jbDJfc2Vjb25kX2NlbGxzXQpjb2NsMl9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlIDwtIEN1c3RvbURpc3RhbmNlKGNvY2wyX3NlY29uZF9zdWJzZXQsIG1hbmhhdHRhbi5kaXN0YW5jZSkKCmRhYnRyYW1fc2Vjb25kX2NlbGxzIDwtICBzYW1wbGUobmFtZXMoc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQgPT0gJ2RhYnRyYW0nXSwgbnVtX2NlbGxzKQpkYWJ0cmFtX3NlY29uZF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssZGFidHJhbV9zZWNvbmRfY2VsbHNdCmRhYnRyYW1fc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSA8LSBDdXN0b21EaXN0YW5jZShkYWJ0cmFtX3NlY29uZF9zdWJzZXQsIG1hbmhhdHRhbi5kaXN0YW5jZSkKCmNpc19zZWNvbmRfY2VsbHMgPC0gIHNhbXBsZShuYW1lcyhzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudCA9PSAnY2lzJ10sIG51bV9jZWxscykKY2lzX3NlY29uZF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY2lzX3NlY29uZF9jZWxsc10KY2lzX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UgPC0gQ3VzdG9tRGlzdGFuY2UoY2lzX3NlY29uZF9zdWJzZXQsIG1hbmhhdHRhbi5kaXN0YW5jZSkKCnBsb3R0aW5nX2RmIDwtIGRhdGEuZnJhbWUoR3JvdXBpbmcgPSBjKHJlcCgnZmlyc3QnLDMqbGVuZ3RoKGNpc19maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UpKSxyZXAoJ3NlY29uZCcsIDMqKGxlbmd0aChjaXNfc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSkpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgTWFuaGF0dGVuX2Rpc3QgPC0gYyhjb2NsMl9maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGRhYnRyYW1fZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlLCBjaXNfZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlLCBjb2NsMl9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlLGRhYnRyYW1fc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSwgY2lzX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UpLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRyZWF0bWVudCA9IGMocmVwKCdDb0NsMiBmaXJzdCcsbGVuZ3RoKGNvY2wyX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSkpLHJlcCgnRGFiL1RyYW0gZmlyc3QnLGxlbmd0aChkYWJ0cmFtX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSkpLHJlcCgnQ2lzcGxhdGluIGZpcnN0JyxsZW5ndGgoY2lzX2ZpcnN0X21hbmhhdHRlbl9kaXN0YW5jZSkpLHJlcCgnQ29DbDIgc2Vjb25kJyxsZW5ndGgoY29jbDJfc2Vjb25kX21hbmhhdHRlbl9kaXN0YW5jZSkpLHJlcCgnRGFiL1RyYW0gc2Vjb25kJyxsZW5ndGgoZGFidHJhbV9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlKSkscmVwKCdDaXNwbGF0aW4gc2Vjb25kJyxsZW5ndGgoY2lzX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UpKSkpCgpnZ3Bsb3QocGxvdHRpbmdfZGYsIGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gTWFuaGF0dGVuX2Rpc3QsIGZpbGwgPSBHcm91cGluZykpICsgZ2VvbV92aW9saW4oKSArIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSkKCnNhdmUuaW1hZ2UoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL3dvcmtzcGFjZV92Mi5SRGF0YScpCgpgYGAKCiMgVHJ5IHBlYXJzb24gLSBodHRwczovL3B1Ym1lZC5uY2JpLm5sbS5uaWguZ292LzMwMTM3MjQ3LwpgYGB7cn0KCiNsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy93b3Jrc3BhY2VfdjIuUkRhdGEnKQoKcm0obWFuaGF0dGVuLmRpc3RhbmNlLCBjb2NsMl9maXJzdF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGRhYnRyYW1fZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlLCBjaXNfZmlyc3RfbWFuaGF0dGVuX2Rpc3RhbmNlLCBjb2NsMl9zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlLCBkYWJ0cmFtX3NlY29uZF9tYW5oYXR0ZW5fZGlzdGFuY2UsIGNpc19zZWNvbmRfbWFuaGF0dGVuX2Rpc3RhbmNlKQpybShjaXMsIGNpc3RvY2lzLCBjaXN0b2NvY2wyLCBjaXN0b2RhYnRyYW0sIGNvY2wyLCBjb2NsMnRvY2lzLCBjb2NsMnRvY29jbDIsIGNvY2wydG9kYWJ0cmFtLCBkYWJ0cmFtLCBkYWJ0cmFtdG9jaXMsIGRhYnRyYW10b2NvY2wyLCBkYWJ0cmFtdG9kYWJ0cmFtKQpnYygpCgojIE1ha2UgbWV0YWRhdGEgb2JqZWN0cyBvZiB0aGUgZmlyc3QgYW5kIHNlY29uZCBjb25kaXRpb25zCnNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50IDwtIHNhcHBseShzdHJzcGxpdChzZWNvbmRfdGltZXBvaW50JE9HX2NvbmRpdGlvbiwgInRvIiksICJbWyIsIDEpCnNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudCA8LSBzYXBwbHkoc3Ryc3BsaXQoc2Vjb25kX3RpbWVwb2ludCRPR19jb25kaXRpb24sICJ0byIpLCAiW1siLCAyKQoKIyBHZXQgaW5wdXQgZGF0YSBhbmQgc3ViZXN0CmlucHV0X2RhdGEgPC0gR2V0QXNzYXlEYXRhKHNlY29uZF90aW1lcG9pbnQsIGFzc2F5ID0gJ1JOQScsIHNsb3QgPSAnc2NhbGUuZGF0YScpCgoKIyBMb29rIGF0IGdyb3VwaW5nIGJhc2VkIG9uIGZpcnN0IHNhbXBsZQpJZGVudHMoc2Vjb25kX3RpbWVwb2ludCkgPC0gc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQKRGltUGxvdChzZWNvbmRfdGltZXBvaW50KQoKY29jbDJfZmlyc3RfY2VsbHMgPC0gIG5hbWVzKHNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudCA9PSAnY29jbDInXQpjb2NsMl9maXJzdF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY29jbDJfZmlyc3RfY2VsbHNdCmNvY2wyX2ZpcnN0X3BlYXJzb24gPC0gY29yKGNvY2wyX2ZpcnN0X3N1YnNldCkKY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0IDwtIGNvY2wyX2ZpcnN0X3BlYXJzb25bbG93ZXIudHJpKGNvY2wyX2ZpcnN0X3BlYXJzb24sIGRpYWcgPSBGQUxTRSldCgpzZXQuc2VlZCgxKQpjb2NsMl9maXJzdF9zdWJzZXRfcmFuZCA8LSBpbnB1dF9kYXRhWyxzYW1wbGUoY29sbmFtZXMoaW5wdXRfZGF0YSksbGVuZ3RoKGNvY2wyX2ZpcnN0X2NlbGxzKSldCmNvY2wyX2ZpcnN0X3BlYXJzb25fcmFuZCA8LSBjb3IoY29jbDJfZmlyc3Rfc3Vic2V0X3JhbmQpCmNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kIDwtIGNvY2wyX2ZpcnN0X3BlYXJzb25fcmFuZFtsb3dlci50cmkoY29jbDJfZmlyc3RfcGVhcnNvbl9yYW5kLCBkaWFnID0gRkFMU0UpXQoKZGFidHJhbV9maXJzdF9jZWxscyA8LSAgbmFtZXMoc2Vjb25kX3RpbWVwb2ludCRmaXJzdF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50ID09ICdkYWJ0cmFtJ10KZGFidHJhbV9maXJzdF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssZGFidHJhbV9maXJzdF9jZWxsc10KZGFidHJhbV9maXJzdF9wZWFyc29uIDwtIGNvcihkYWJ0cmFtX2ZpcnN0X3N1YnNldCkKZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHQgPC0gZGFidHJhbV9maXJzdF9wZWFyc29uW2xvd2VyLnRyaShkYWJ0cmFtX2ZpcnN0X3BlYXJzb24sIGRpYWcgPSBGQUxTRSldCgpzZXQuc2VlZCgxKQpkYWJ0cmFtX2ZpcnN0X3N1YnNldF9yYW5kIDwtIGlucHV0X2RhdGFbLHNhbXBsZShjb2xuYW1lcyhpbnB1dF9kYXRhKSxsZW5ndGgoZGFidHJhbV9maXJzdF9jZWxscykpXQpkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fcmFuZCA8LSBjb3IoZGFidHJhbV9maXJzdF9zdWJzZXRfcmFuZCkKZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCA8LSBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fcmFuZFtsb3dlci50cmkoZGFidHJhbV9maXJzdF9wZWFyc29uX3JhbmQsIGRpYWcgPSBGQUxTRSldCgpjaXNfZmlyc3RfY2VsbHMgPC0gIG5hbWVzKHNlY29uZF90aW1lcG9pbnQkZmlyc3RfdHJlYXRtZW50KVtzZWNvbmRfdGltZXBvaW50JGZpcnN0X3RyZWF0bWVudCA9PSAnY2lzJ10KY2lzX2ZpcnN0X3N1YnNldCA8LSBpbnB1dF9kYXRhWyxjaXNfZmlyc3RfY2VsbHNdCmNpc19maXJzdF9wZWFyc29uIDwtIGNvcihjaXNfZmlyc3Rfc3Vic2V0KQpjaXNfZmlyc3RfcGVhcnNvbl9maWx0IDwtIGNpc19maXJzdF9wZWFyc29uW2xvd2VyLnRyaShjaXNfZmlyc3RfcGVhcnNvbiwgZGlhZyA9IEZBTFNFKV0KCnNldC5zZWVkKDEpCmNpc19maXJzdF9zdWJzZXRfcmFuZCA8LSBpbnB1dF9kYXRhWyxzYW1wbGUoY29sbmFtZXMoaW5wdXRfZGF0YSksbGVuZ3RoKGNpc19maXJzdF9jZWxscykpXQpjaXNfZmlyc3RfcGVhcnNvbl9yYW5kIDwtIGNvcihjaXNfZmlyc3Rfc3Vic2V0X3JhbmQpCmNpc19maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCA8LSBjaXNfZmlyc3RfcGVhcnNvbl9yYW5kW2xvd2VyLnRyaShjaXNfZmlyc3RfcGVhcnNvbl9yYW5kLCBkaWFnID0gRkFMU0UpXQoKSWRlbnRzKHNlY29uZF90aW1lcG9pbnQpIDwtIHNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudApEaW1QbG90KHNlY29uZF90aW1lcG9pbnQpCgpjb2NsMl9zZWNvbmRfY2VsbHMgPC0gIG5hbWVzKHNlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudClbc2Vjb25kX3RpbWVwb2ludCRzZWNvbmRfdHJlYXRtZW50ID09ICdjb2NsMiddCmNvY2wyX3NlY29uZF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY29jbDJfc2Vjb25kX2NlbGxzXQpjb2NsMl9zZWNvbmRfcGVhcnNvbiA8LSBjb3IoY29jbDJfc2Vjb25kX3N1YnNldCkKY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCA8LSBjb2NsMl9zZWNvbmRfcGVhcnNvbltsb3dlci50cmkoY29jbDJfc2Vjb25kX3BlYXJzb24sIGRpYWcgPSBGQUxTRSldCgpzZXQuc2VlZCgxKQpjb2NsMl9zZWNvbmRfc3Vic2V0X3JhbmQgPC0gaW5wdXRfZGF0YVssc2FtcGxlKGNvbG5hbWVzKGlucHV0X2RhdGEpLGxlbmd0aChjb2NsMl9zZWNvbmRfY2VsbHMpKV0KY29jbDJfc2Vjb25kX3BlYXJzb25fcmFuZCA8LSBjb3IoY29jbDJfc2Vjb25kX3N1YnNldF9yYW5kKQpjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQgPC0gY29jbDJfc2Vjb25kX3BlYXJzb25fcmFuZFtsb3dlci50cmkoY29jbDJfc2Vjb25kX3BlYXJzb25fcmFuZCwgZGlhZyA9IEZBTFNFKV0KCmRhYnRyYW1fc2Vjb25kX2NlbGxzIDwtICBuYW1lcyhzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudCA9PSAnZGFidHJhbSddCmRhYnRyYW1fc2Vjb25kX3N1YnNldCA8LSBpbnB1dF9kYXRhWyxkYWJ0cmFtX3NlY29uZF9jZWxsc10KZGFidHJhbV9zZWNvbmRfcGVhcnNvbiA8LSBjb3IoZGFidHJhbV9zZWNvbmRfc3Vic2V0KQpkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQgPC0gZGFidHJhbV9zZWNvbmRfcGVhcnNvbltsb3dlci50cmkoZGFidHJhbV9zZWNvbmRfcGVhcnNvbiwgZGlhZyA9IEZBTFNFKV0KCnNldC5zZWVkKDEpCmRhYnRyYW1fc2Vjb25kX3N1YnNldF9yYW5kIDwtIGlucHV0X2RhdGFbLHNhbXBsZShjb2xuYW1lcyhpbnB1dF9kYXRhKSxsZW5ndGgoZGFidHJhbV9zZWNvbmRfY2VsbHMpKV0KZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9yYW5kIDwtIGNvcihkYWJ0cmFtX3NlY29uZF9zdWJzZXRfcmFuZCkKZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQgPC0gZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9yYW5kW2xvd2VyLnRyaShkYWJ0cmFtX3NlY29uZF9wZWFyc29uX3JhbmQsIGRpYWcgPSBGQUxTRSldCgpjaXNfc2Vjb25kX2NlbGxzIDwtICBuYW1lcyhzZWNvbmRfdGltZXBvaW50JHNlY29uZF90cmVhdG1lbnQpW3NlY29uZF90aW1lcG9pbnQkc2Vjb25kX3RyZWF0bWVudCA9PSAnY2lzJ10KY2lzX3NlY29uZF9zdWJzZXQgPC0gaW5wdXRfZGF0YVssY2lzX3NlY29uZF9jZWxsc10KY2lzX3NlY29uZF9wZWFyc29uIDwtIGNvcihjaXNfc2Vjb25kX3N1YnNldCkKY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQgPC0gY2lzX3NlY29uZF9wZWFyc29uW2xvd2VyLnRyaShjaXNfc2Vjb25kX3BlYXJzb24sIGRpYWcgPSBGQUxTRSldCgpzZXQuc2VlZCgxKQpjaXNfc2Vjb25kX3N1YnNldF9yYW5kIDwtIGlucHV0X2RhdGFbLHNhbXBsZShjb2xuYW1lcyhpbnB1dF9kYXRhKSxsZW5ndGgoY2lzX3NlY29uZF9jZWxscykpXQpjaXNfc2Vjb25kX3BlYXJzb25fcmFuZCA8LSBjb3IoY2lzX3NlY29uZF9zdWJzZXRfcmFuZCkKY2lzX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCA8LSBjaXNfc2Vjb25kX3BlYXJzb25fcmFuZFtsb3dlci50cmkoY2lzX3NlY29uZF9wZWFyc29uX3JhbmQsIGRpYWcgPSBGQUxTRSldCgpzYXZlLmltYWdlKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy93b3Jrc3BhY2VfdjMuUkRhdGEnKQoKIyBTYXZlIENvQ2wyIG91dHB1dHMKc2F2ZShjb2NsMl9maXJzdF9wZWFyc29uLCBjb2NsMl9maXJzdF9wZWFyc29uX3JhbmQsIGNvY2wyX2ZpcnN0X3N1YnNldCwgY29jbDJfZmlyc3Rfc3Vic2V0X3JhbmQsIGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uLCBjb2NsMl9zZWNvbmRfcGVhcnNvbl9yYW5kLCBjb2NsMl9zZWNvbmRfc3Vic2V0LCBjb2NsMl9zZWNvbmRfc3Vic2V0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jb2NsMl9wZWFyc29uX3Jlc3VsdHMuUkRhdGEnKQpybShjb2NsMl9maXJzdF9wZWFyc29uLCBjb2NsMl9maXJzdF9wZWFyc29uX3JhbmQsIGNvY2wyX2ZpcnN0X3N1YnNldCwgY29jbDJfZmlyc3Rfc3Vic2V0X3JhbmQsIGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uLCBjb2NsMl9zZWNvbmRfcGVhcnNvbl9yYW5kLCBjb2NsMl9zZWNvbmRfc3Vic2V0LCBjb2NsMl9zZWNvbmRfc3Vic2V0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCkKCiMgU2F2ZSBkYWJ0cmFtIG91dHB1dHMKc2F2ZShkYWJ0cmFtX2ZpcnN0X3BlYXJzb24sIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9yYW5kLCBkYWJ0cmFtX2ZpcnN0X3N1YnNldCwgZGFidHJhbV9maXJzdF9zdWJzZXRfcmFuZCwgZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb24sIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fcmFuZCwgZGFidHJhbV9zZWNvbmRfc3Vic2V0LCBkYWJ0cmFtX3NlY29uZF9zdWJzZXRfcmFuZCwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9kYWJ0cmFtX3BlYXJzb25fcmVzdWx0cy5SRGF0YScpCnJtKGRhYnRyYW1fZmlyc3RfcGVhcnNvbiwgZGFidHJhbV9maXJzdF9wZWFyc29uX3JhbmQsIGRhYnRyYW1fZmlyc3Rfc3Vic2V0LCBkYWJ0cmFtX2ZpcnN0X3N1YnNldF9yYW5kLCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCwgZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbiwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9yYW5kLCBkYWJ0cmFtX3NlY29uZF9zdWJzZXQsIGRhYnRyYW1fc2Vjb25kX3N1YnNldF9yYW5kLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKQoKIyBTYXZlIGNpcyBvdXRwdXRzCnNhdmUoY2lzX2ZpcnN0X3BlYXJzb24sIGNpc19maXJzdF9wZWFyc29uX3JhbmQsIGNpc19maXJzdF9zdWJzZXQsIGNpc19maXJzdF9zdWJzZXRfcmFuZCwgY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCwgY2lzX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBjaXNfc2Vjb25kX3BlYXJzb24sIGNpc19zZWNvbmRfcGVhcnNvbl9yYW5kLCBjaXNfc2Vjb25kX3N1YnNldCwgY2lzX3NlY29uZF9zdWJzZXRfcmFuZCwgY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQsIGZpbGUgPSAnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY2lzX3BlYXJzb25fcmVzdWx0cy5SRGF0YScpCnJtKGNpc19maXJzdF9wZWFyc29uLCBjaXNfZmlyc3RfcGVhcnNvbl9yYW5kLCBjaXNfZmlyc3Rfc3Vic2V0LCBjaXNfZmlyc3Rfc3Vic2V0X3JhbmQsIGNpc19maXJzdF9wZWFyc29uX2ZpbHQsIGNpc19maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgY2lzX3NlY29uZF9wZWFyc29uLCBjaXNfc2Vjb25kX3BlYXJzb25fcmFuZCwgY2lzX3NlY29uZF9zdWJzZXQsIGNpc19zZWNvbmRfc3Vic2V0X3JhbmQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0LCBjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKQpgYGAKCiMgU3RhdGlzdGljYWwgYW5hbHlzaXMgYW5kIHBsb3R0aW5nIG9mIHBlYXJzb24gbWV0cmljcyAtIENvQ2wyCmBgYHtyfQpsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jb2NsMl9wZWFyc29uX3Jlc3VsdHMuUkRhdGEnKSAjIExvYWQgZGF0YQoKcGVhcnNvbl90dGVzdF9jb2NsMl9maXJzdHZzcmFuZCA8LSB0LnRlc3QoY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0LCBjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgIHBhaXJlZCA9IEYpCnBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNyYW5kIDwtIHQudGVzdChjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0LCBjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQsICBwYWlyZWQgPSBGKQpwZWFyc29uX3R0ZXN0X2NvY2wyX3NlY29uZHZzZmlyc3QgPC0gdC50ZXN0KGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCwgIHBhaXJlZCA9IEYpCnBlYXJzb25fdHRlc3RfY29jbDJfcmFuZHZzcmFuZCA8LSB0LnRlc3QoY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCBjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgIHBhaXJlZCA9IEYpCgpybShjb2NsMl9maXJzdF9wZWFyc29uLCBjb2NsMl9maXJzdF9wZWFyc29uX3JhbmQsIGNvY2wyX2ZpcnN0X3N1YnNldCwgY29jbDJfZmlyc3Rfc3Vic2V0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uLCBjb2NsMl9zZWNvbmRfcGVhcnNvbl9yYW5kLCBjb2NsMl9zZWNvbmRfc3Vic2V0LCBjb2NsMl9zZWNvbmRfc3Vic2V0X3JhbmQpCgpwbG90dGluZ19kZl9wZWFyc29uX2NvY2wyIDwtIGRhdGEuZnJhbWUoR3JvdXBpbmcgPSBjKHJlcCgnZmlyc3QnLGxlbmd0aChjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdyYW5kb20nLGxlbmd0aChjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdzZWNvbmQnLCBsZW5ndGgoY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCkpLCByZXAoJ3JhbmRvbScsIGxlbmd0aChjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0KSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgIFBlYXJzb24gPSBjKGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdCwgY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNvY2wyX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gYyhyZXAoJ0NvQ2wyIGZpcnN0JyxsZW5ndGgoY29jbDJfZmlyc3RfcGVhcnNvbl9maWx0KSksIHJlcCgnQ29DbDIgZmlyc3QgcmFuZCcsIGxlbmd0aChjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCkpLHJlcCgnQ29DbDIgc2Vjb25kJyxsZW5ndGgoY29jbDJfc2Vjb25kX3BlYXJzb25fZmlsdCkpLHJlcCgnQ29DbDIgc2Vjb25kIHJhbmQnLGxlbmd0aChjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQpKSkpCmNvbG5hbWVzKHBsb3R0aW5nX2RmX3BlYXJzb25fY29jbDIpIDwtIGMoJ0dyb3VwaW5nJywnUGVhcnNvbicsJ1RyZWF0bWVudCcpCgpybShjb2NsMl9maXJzdF9wZWFyc29uX2ZpbHQsIGNvY2wyX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0LCBjb2NsMl9zZWNvbmRfcGVhcnNvbl9maWx0X3JhbmQpCmdjKCkKCnBkZignMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvY29jbDJfcGVhcnNvbl9wbG90X3N1YnNhbXBsZWQucGRmJykKc2V0LnNlZWQoMSkKZ2dwbG90KHBsb3R0aW5nX2RmX3BlYXJzb25fY29jbDJbc2FtcGxlKDE6bnJvdyhwbG90dGluZ19kZl9wZWFyc29uX2NvY2wyKSwgMTAwMDAwMDApLF0sIGFlcyh4ID0gVHJlYXRtZW50LCB5ID0gUGVhcnNvbiwgZmlsbCA9IEdyb3VwaW5nKSkgKyBnZW9tX3Zpb2xpbigpICsgZ2VvbV9ib3hwbG90KHdpZHRoID0gMC4xLCBvdXRsaWVyLnNoYXBlID0gTkEpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YygiI0ZGMDAwMCIsICIjRDNEM0QzIiwgIiMwMDAwRkYiKSkKZGV2Lm9mZigpCgojIFNhdmUgb3V0cHV0cwpzYXZlKHBlYXJzb25fdHRlc3RfY29jbDJfZmlyc3R2c3JhbmQsIHBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNmaXJzdCwgcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c3JhbmQsIHBlYXJzb25fdHRlc3RfY29jbDJfcmFuZHZzcmFuZCwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jb2NsMl9wZWFyc29uX3ZhbHVlcy5SRGF0YScpCnJtKHBlYXJzb25fdHRlc3RfY29jbDJfZmlyc3R2c3JhbmQsIHBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNmaXJzdCwgcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c3JhbmQsIHBlYXJzb25fdHRlc3RfY29jbDJfcmFuZHZzcmFuZCkKCnNhdmUocGxvdHRpbmdfZGZfcGVhcnNvbl9jb2NsMiwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jb2NsMl9wZWFyc29uX3Bsb3R0aW5nX2RmLlJEYXRhJykKcm0ocGxvdHRpbmdfZGZfcGVhcnNvbl9jb2NsMikKYGBgCgojIFN0YXRpc3RpY2FsIGFuYWx5c2lzIGFuZCBwbG90dGluZyBvZiBwZWFyc29uIG1ldHJpY3MgLSBkYWJ0cmFtCmBgYHtyfQpsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9kYWJ0cmFtX3BlYXJzb25fcmVzdWx0cy5SRGF0YScpICMgTG9hZCBkYXRhCgpwZWFyc29uX3R0ZXN0X2RhYnRyYW1fZmlyc3R2c3JhbmQgPC0gdC50ZXN0KGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCAgcGFpcmVkID0gRikKcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3NlY29uZHZzcmFuZCA8LSB0LnRlc3QoZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCwgIHBhaXJlZCA9IEYpCnBlYXJzb25fdHRlc3RfZGFidHJhbV9zZWNvbmR2c2ZpcnN0IDwtIHQudGVzdChkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHQsIGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0LCAgcGFpcmVkID0gRikKcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3JhbmR2c3JhbmQgPC0gdC50ZXN0KGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCBkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCAgcGFpcmVkID0gRikKCnJtKGRhYnRyYW1fZmlyc3RfcGVhcnNvbiwgZGFidHJhbV9maXJzdF9wZWFyc29uX3JhbmQsIGRhYnRyYW1fZmlyc3Rfc3Vic2V0LCBkYWJ0cmFtX2ZpcnN0X3N1YnNldF9yYW5kLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uLCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX3JhbmQsIGRhYnRyYW1fc2Vjb25kX3N1YnNldCwgZGFidHJhbV9zZWNvbmRfc3Vic2V0X3JhbmQpCgpwbG90dGluZ19kZl9wZWFyc29uX2RhYnRyYW0gPC0gZGF0YS5mcmFtZShHcm91cGluZyA9IGMocmVwKCdmaXJzdCcsbGVuZ3RoKGRhYnRyYW1fZmlyc3RfcGVhcnNvbl9maWx0KSksIHJlcCgncmFuZG9tJyxsZW5ndGgoZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdzZWNvbmQnLCBsZW5ndGgoZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0KSksIHJlcCgncmFuZG9tJywgbGVuZ3RoKGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdCkpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBQZWFyc29uID0gYyhkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCwgZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gYyhyZXAoJ2RhYnRyYW0gZmlyc3QnLGxlbmd0aChkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ2RhYnRyYW0gZmlyc3QgcmFuZCcsIGxlbmd0aChkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kKSkscmVwKCdkYWJ0cmFtIHNlY29uZCcsbGVuZ3RoKGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdCkpLHJlcCgnZGFidHJhbSBzZWNvbmQgcmFuZCcsbGVuZ3RoKGRhYnRyYW1fc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKSkpKQpjb2xuYW1lcyhwbG90dGluZ19kZl9wZWFyc29uX2RhYnRyYW0pIDwtIGMoJ0dyb3VwaW5nJywnUGVhcnNvbicsJ1RyZWF0bWVudCcpCgpybShkYWJ0cmFtX2ZpcnN0X3BlYXJzb25fZmlsdCwgZGFidHJhbV9maXJzdF9wZWFyc29uX2ZpbHRfcmFuZCwgZGFidHJhbV9zZWNvbmRfcGVhcnNvbl9maWx0LCBkYWJ0cmFtX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCkKZ2MoKQoKcGRmKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9kYWJ0cmFtX3BlYXJzb25fcGxvdF9zdWJzYW1wbGVkLnBkZicpCnNldC5zZWVkKDEpCmdncGxvdChwbG90dGluZ19kZl9wZWFyc29uX2RhYnRyYW1bc2FtcGxlKDE6bnJvdyhwbG90dGluZ19kZl9wZWFyc29uX2RhYnRyYW0pLCAxMDAwMDAwMCksXSwgYWVzKHggPSBUcmVhdG1lbnQsIHkgPSBQZWFyc29uLCBmaWxsID0gR3JvdXBpbmcpKSArIGdlb21fdmlvbGluKCkgKyBnZW9tX2JveHBsb3Qod2lkdGggPSAwLjEsIG91dGxpZXIuc2hhcGUgPSBOQSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCIjRkYwMDAwIiwgIiNEM0QzRDMiLCAiIzAwMDBGRiIpKQpkZXYub2ZmKCkKCiMgU2F2ZSBvdXRwdXRzCnNhdmUocGVhcnNvbl90dGVzdF9kYWJ0cmFtX2ZpcnN0dnNyYW5kLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNmaXJzdCwgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3NlY29uZHZzcmFuZCxwZWFyc29uX3R0ZXN0X2RhYnRyYW1fcmFuZHZzcmFuZCwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9kYWJ0cmFtX3BlYXJzb25fdmFsdWVzLlJEYXRhJykKcm0ocGVhcnNvbl90dGVzdF9kYWJ0cmFtX2ZpcnN0dnNyYW5kLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNmaXJzdCwgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3NlY29uZHZzcmFuZCwgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3JhbmR2c3JhbmQpCgpzYXZlKHBsb3R0aW5nX2RmX3BlYXJzb25fZGFidHJhbSwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9kYWJ0cmFtX3BlYXJzb25fcGxvdHRpbmdfZGYuUkRhdGEnKQpybShwbG90dGluZ19kZl9wZWFyc29uX2RhYnRyYW0pCmBgYAoKIyBTdGF0aXN0aWNhbCBhbmFseXNpcyBhbmQgcGxvdHRpbmcgb2YgcGVhcnNvbiBtZXRyaWNzIC0gY2lzCmBgYHtyfQpsb2FkKCcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9jaXNfcGVhcnNvbl9yZXN1bHRzLlJEYXRhJykgIyBMb2FkIGRhdGEKCnBlYXJzb25fdHRlc3RfY2lzX2ZpcnN0dnNyYW5kIDwtIHQudGVzdChjaXNfZmlyc3RfcGVhcnNvbl9maWx0LCBjaXNfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsICBwYWlyZWQgPSBGKQpwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c3JhbmQgPC0gdC50ZXN0KGNpc19zZWNvbmRfcGVhcnNvbl9maWx0LCBjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCAgcGFpcmVkID0gRikKcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNmaXJzdCA8LSB0LnRlc3QoY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQsIGNpc19maXJzdF9wZWFyc29uX2ZpbHQsICBwYWlyZWQgPSBGKQpwZWFyc29uX3R0ZXN0X2Npc19yYW5kdnNyYW5kIDwtIHQudGVzdChjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kLCBjaXNfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsICBwYWlyZWQgPSBGKQoKcm0oY2lzX2ZpcnN0X3BlYXJzb24sIGNpc19maXJzdF9wZWFyc29uX3JhbmQsIGNpc19maXJzdF9zdWJzZXQsIGNpc19maXJzdF9zdWJzZXRfcmFuZCwgY2lzX3NlY29uZF9wZWFyc29uLCBjaXNfc2Vjb25kX3BlYXJzb25fcmFuZCwgY2lzX3NlY29uZF9zdWJzZXQsIGNpc19zZWNvbmRfc3Vic2V0X3JhbmQpCgpwbG90dGluZ19kZl9wZWFyc29uX2NpcyA8LSBkYXRhLmZyYW1lKEdyb3VwaW5nID0gYyhyZXAoJ2ZpcnN0JyxsZW5ndGgoY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCkpLCByZXAoJ3JhbmRvbScsbGVuZ3RoKGNpc19maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdzZWNvbmQnLCBsZW5ndGgoY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdyYW5kb20nLCBsZW5ndGgoY2lzX3NlY29uZF9wZWFyc29uX2ZpbHQpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgUGVhcnNvbiA9IGMoY2lzX2ZpcnN0X3BlYXJzb25fZmlsdCwgY2lzX2ZpcnN0X3BlYXJzb25fZmlsdF9yYW5kLCBjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCwgY2lzX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgVHJlYXRtZW50ID0gYyhyZXAoJ2NpcyBmaXJzdCcsbGVuZ3RoKGNpc19maXJzdF9wZWFyc29uX2ZpbHQpKSwgcmVwKCdjaXMgZmlyc3QgcmFuZCcsIGxlbmd0aChjaXNfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQpKSxyZXAoJ2NpcyBzZWNvbmQnLGxlbmd0aChjaXNfc2Vjb25kX3BlYXJzb25fZmlsdCkpLHJlcCgnY2lzIHNlY29uZCByYW5kJyxsZW5ndGgoY2lzX3NlY29uZF9wZWFyc29uX2ZpbHRfcmFuZCkpKSkKY29sbmFtZXMocGxvdHRpbmdfZGZfcGVhcnNvbl9jaXMpIDwtIGMoJ0dyb3VwaW5nJywnUGVhcnNvbicsJ1RyZWF0bWVudCcpCgpybShjaXNfZmlyc3RfcGVhcnNvbl9maWx0LCBjaXNfZmlyc3RfcGVhcnNvbl9maWx0X3JhbmQsIGNpc19zZWNvbmRfcGVhcnNvbl9maWx0LCBjaXNfc2Vjb25kX3BlYXJzb25fZmlsdF9yYW5kKQpnYygpCgpwZGYoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2Npc19wZWFyc29uX3Bsb3Rfc3Vic2FtcGxlZC5wZGYnKQpzZXQuc2VlZCgxKQpnZ3Bsb3QocGxvdHRpbmdfZGZfcGVhcnNvbl9jaXNbc2FtcGxlKDE6bnJvdyhwbG90dGluZ19kZl9wZWFyc29uX2NpcyksIDEwMDAwMDAwKSxdLCBhZXMoeCA9IFRyZWF0bWVudCwgeSA9IFBlYXJzb24sIGZpbGwgPSBHcm91cGluZykpICsgZ2VvbV92aW9saW4oKSArIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuMSwgb3V0bGllci5zaGFwZSA9IE5BKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMoIiNGRjAwMDAiLCAiI0QzRDNEMyIsICIjMDAwMEZGIikpCmRldi5vZmYoKQoKIyBTYXZlIG91dHB1dHMKc2F2ZShwZWFyc29uX3R0ZXN0X2Npc19maXJzdHZzcmFuZCwgcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNmaXJzdCwgcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNyYW5kLCBwZWFyc29uX3R0ZXN0X2Npc19yYW5kdnNyYW5kLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2Npc19wZWFyc29uX3ZhbHVlcy5SRGF0YScpCnJtKHBlYXJzb25fdHRlc3RfY2lzX2ZpcnN0dnNyYW5kLCBwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c2ZpcnN0LCBwZWFyc29uX3R0ZXN0X2Npc19zZWNvbmR2c3JhbmQsIHBlYXJzb25fdHRlc3RfY2lzX3JhbmR2c3JhbmQpCgpzYXZlKHBsb3R0aW5nX2RmX3BlYXJzb25fY2lzLCBmaWxlID0gJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2Npc19wZWFyc29uX3Bsb3R0aW5nX2RmLlJEYXRhJykKcm0ocGxvdHRpbmdfZGZfcGVhcnNvbl9jaXMpCmBgYAoKIyBMb2FkIGluIHRoZSB0dGVzdCBkYXRhIGFuZCBjb21waWxlIGludG8gZXhjZWwgc2hlZXQKYGBge3J9CmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2NvY2wyX3BlYXJzb25fdmFsdWVzLlJEYXRhJykKbG9hZCgnMjAyMl8wMV8xNF9hbmFseXNpc19zY3JpcHRzLzIwMjJfMDVfMjdfYW5hbHlzaXMvQ29uZGl0aW9uX0NsdXN0ZXJpbmcvZGFidHJhbV9wZWFyc29uX3ZhbHVlcy5SRGF0YScpCmxvYWQoJzIwMjJfMDFfMTRfYW5hbHlzaXNfc2NyaXB0cy8yMDIyXzA1XzI3X2FuYWx5c2lzL0NvbmRpdGlvbl9DbHVzdGVyaW5nL2Npc19wZWFyc29uX3ZhbHVlcy5SRGF0YScpCgpjb21wYXJpc29ucyA8LSAgYygnZGFidHJhbV9maXJzdHZzcmFuZCcsICdkYWJ0cmFtX3NlY29uZHZzcmFuZCcsICdkYWJ0cmFtX3JhbmR2c3JhbmQnLCAnZGFidHJhbV9zZWNvbmR2c2ZpcnN0JywKICAgICAgICAgICAgICAgICAgJ2NvY2wyX2ZpcnN0dnNyYW5kJywgJ2NvY2wyX3NlY29uZHZzcmFuZCcsICdjb2NsMl9yYW5kdnNyYW5kJywgJ2NvY2wyX3NlY29uZHZzZmlyc3QnLAogICAgICAgICAgICAgICAgICAnY2lzX2ZpcnN0dnNyYW5kJywgJ2Npc19zZWNvbmR2c3JhbmQnLCAnY2lzX3JhbmR2c3JhbmQnLCAnY2lzX3NlY29uZHZzZmlyc3QnKQoKdF9zdGF0aXN0aWMgPC0gYyhwZWFyc29uX3R0ZXN0X2RhYnRyYW1fZmlyc3R2c3JhbmQkc3RhdGlzdGljLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNyYW5kJHN0YXRpc3RpYywgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3JhbmR2c3JhbmQkc3RhdGlzdGljLCBwZWFyc29uX3R0ZXN0X2RhYnRyYW1fc2Vjb25kdnNmaXJzdCRzdGF0aXN0aWMsCiAgICAgICAgICAgICAgICAgcGVhcnNvbl90dGVzdF9jb2NsMl9maXJzdHZzcmFuZCRzdGF0aXN0aWMsIHBlYXJzb25fdHRlc3RfY29jbDJfc2Vjb25kdnNyYW5kJHN0YXRpc3RpYyxwZWFyc29uX3R0ZXN0X2NvY2wyX3JhbmR2c3JhbmQkc3RhdGlzdGljLCBwZWFyc29uX3R0ZXN0X2NvY2wyX3NlY29uZHZzZmlyc3Qkc3RhdGlzdGljLAogICAgICAgICAgICAgICAgIHBlYXJzb25fdHRlc3RfY2lzX2ZpcnN0dnNyYW5kJHN0YXRpc3RpYywgcGVhcnNvbl90dGVzdF9jaXNfc2Vjb25kdnNyYW5kJHN0YXRpc3RpYywgcGVhcnNvbl90dGVzdF9jaXNfcmFuZHZzcmFuZCRzdGF0aXN0aWMsIHBlYXJzb25fdHRlc3RfY2lzX3NlY29uZHZzZmlyc3Qkc3RhdGlzdGljKQoKdF9wdmFsIDwtIGMocGVhcnNvbl90dGVzdF9kYWJ0cmFtX2ZpcnN0dnNyYW5kJHAudmFsdWUsIHBlYXJzb25fdHRlc3RfZGFidHJhbV9zZWNvbmR2c3JhbmQkcC52YWx1ZSwgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3JhbmR2c3JhbmQkcC52YWx1ZSwgcGVhcnNvbl90dGVzdF9kYWJ0cmFtX3NlY29uZHZzZmlyc3QkcC52YWx1ZSwKICAgICAgICAgICAgcGVhcnNvbl90dGVzdF9jb2NsMl9maXJzdHZzcmFuZCRwLnZhbHVlLCBwZWFyc29uX3R0ZXN0X2NvY2wyX3NlY29uZHZzcmFuZCRwLnZhbHVlLCBwZWFyc29uX3R0ZXN0X2NvY2wyX3JhbmR2c3JhbmQkcC52YWx1ZSwgcGVhcnNvbl90dGVzdF9jb2NsMl9zZWNvbmR2c2ZpcnN0JHAudmFsdWUsCiAgICAgICAgICAgIHBlYXJzb25fdHRlc3RfY2lzX2ZpcnN0dnNyYW5kJHAudmFsdWUsIHBlYXJzb25fdHRlc3RfY2lzX3NlY29uZHZzcmFuZCRwLnZhbHVlLCBwZWFyc29uX3R0ZXN0X2Npc19yYW5kdnNyYW5kJHAudmFsdWUsIHBlYXJzb25fdHRlc3RfY2lzX3NlY29uZHZzZmlyc3QkcC52YWx1ZSkKCnR0ZXN0X2RmIDwtIGRhdGEuZnJhbWUoJ0NvbXBhcmlzb25zJyA9IGNvbXBhcmlzb25zLCAnVCB0ZXN0IHN0YXRpc3RpYycgPSB0X3N0YXRpc3RpYywgJ3AgdmFsdWUnID0gdF9wdmFsKQoKd3JpdGUueGxzeCh0dGVzdF9kZiwgZmlsZSA9ICcyMDIyXzAxXzE0X2FuYWx5c2lzX3NjcmlwdHMvMjAyMl8wNV8yN19hbmFseXNpcy9Db25kaXRpb25fQ2x1c3RlcmluZy9wZWFyc29uX3R0ZXN0X3N0YXRpc3RpY3MueGxzeCcpCmBgYAoKCgo=